操作符
??
a??b;
//等同于
(a!==null&&a!==undefined)?a:b;
void
void是一个操作符,该操作符指定要计算一个表达式但是返回值永远是undefined。 调用方法同时防止页面刷新 新浪微博,淘宝等大站的首页JS操作的href都是javascript:void(0) 既保证了返回值是undefined,又保证如果连接点击需要处理一些代码,随时将0替换掉就可以。
// 阻止链接跳转,URL不会有任何变化
<a href="javascript:void(0)" rel="nofollow ugc">点击此处</a>
// 虽然阻止了链接跳转,但URL尾部会多个#,改变了当前URL。(# 主要用于配合 location.hash)
<a href="#" rel="nofollow ugc">点击此处</a>
// 同理,# 可以的话,? 也能达到阻止页面跳转的效果,但也相同的改变了URL。(? 主要用于配合 location.search)
<a href="?" rel="nofollow ugc">点击此处</a>
// Chrome 中即使 javascript:0; 也没变化,firefox中会变成一个字符串0
<a href="javascript:0" rel="nofollow ugc">点击此处</a>
with语句
针对一个对象反复操作,严格模式不允许
let qs=location.search.substring(1);
let host=location.hostname;
//可替换为
with(location){
let qs=search.substring(1);
let host=hostname;
}
模板字面量
字面量:直接出现在程序中的数据值,包含整数字面量1、浮点字面量、字符串字面量等
模板字面量:允许嵌入表达式的字符串字面量,使用反引号 () 来代替普通字符串中的用双引号和单引号来定义字符串
字符串插值:模板字符串可以包含特定语法 ${expression} 的占位符。占位符中的表达式和周围的文本会一起传递给一个默认函数,该函数负责将所有的部分连接起来。
arr[part_key${i}]; //访问part_key*的属性
动态构建字符串时使用模板字符串而不是拼接
// bad
function sayHi(name) {
return 'How are you, ' + name + '?';
}
// good
function sayHi(name) {
return `How are you, ${name}?`;
}
标签函数
如果一个模板字符串由表达式开头,则该字符串被称为带标签的模板字符串,该表达式通常是一个函数,它会在模板字符串处理后被调用,在输出最终结果前,你都可以通过该函数来对模板字符串进行操作处理。
在模版字符串内使用反引号(`)时,需要在它前面加转义符(\)
// that ${ person } is a ${ age }调用标签函数,第一个参数是一个数组,对应模板中的字符串。变量对应形参
var person = 'Mike';
var age = 28;
function myTag(strings, personExp, ageExp) {
var str0 = strings[0]; // "that "
var str1 = strings[1]; // " is a "
var ageStr;
if (ageExp > 99){
ageStr = 'centenarian';
} else {
ageStr = 'youngster';
}
return str0 + personExp + str1 + ageStr;
}
var output = myTag`that ${ person } is a ${ age }`;
console.log(output);
// that Mike is a youngster
注意 :如果标签函数传参首尾有变量会产生空元素,如下
myTag` ${ person } is a ${ age }`;
原理:标签函数拆分传参的方式是
args.split(/\$\{.*?\}/)
'|b|c'.split('|'); // [ ' ', 'b' , 'c' ]
应用
模板提供了插值语法,同时也引入了XSS的风险(当我们把插值的权力交给用户),所以这时候就需要标签函数来过滤、编码、组合。
eval()
一个危险的函数, 拥有与调用者相同的权限执行代码。再者第三方代码可以看到某一个 eval() 被调用时的作用域
eval() 通常比其他替代方法更慢,因为它必须调用 JS 解释器。现代JavaScript解释器将javascript转换为机器代码。 这意味着任何变量命名的概念都会被删除。 因此,任意一个eval的使用都会强制浏览器进行冗长的变量名称查找,以确定变量在机器代码中的位置并设置其值。 另外,新内容将会通过 eval() 引进给变量, 比如更改该变量的类型,因此会强制浏览器重新执行所有已经生成的机器代码以进行补偿。
一个非常好的eval替代方法:只需使用 window.Function
断言assert
断言是 调试技巧, 在大多编程语言中都支持断言这种机制来调式程序,JavaScript 借助浏览器提供的 console 方法 来实现的。
提前预判 程序的结果,如果之后执行的程序不符合我们的预判,那么则报错,例如下面这个例子。
function f(n) {
console.assert(n !== 0, '零不能作为被除数') // 这里就是断言 | 提前预判
return 10 / n
}
console.log(f(1)) // 10
console.log(f(2)) // 5
console.log(f(0)) // 报错 | Assertion failed: 零不能作为被除数