在日常工作中,undefined使用的频率也是很高的,比如:
function testFun () {
var firstArg = arguments[0] !== undefined ? arguments[0] : 2;
console.log(firstArg);
}
上述代码估计各位都有写过,在ES6函数参数默认值之前,我们要设置参数的默认值常常需要判断当前参数是否存在,当不存在时给它一个默认值。但是我想告诉大家的是undefind是可以被赋值的。
function test() {
undefined = 123;
console.log(undefined)
}
test() //undefined
function test1() {
var undefined = 123;
console.log(undefined)
}
test1() //123
出现上述问题的原因是:undefined 在 ES5 中已经是全局对象的一个只读(read-only)属性了,全局作用域它不能被重写。但是在局部作用域中,还是可以被重写的。兴许有人会说我能保证我的代码不会出这个问题,但是在这个通力合作的时代,我们得从源头解决问题,而不是靠人为习惯。当然成熟的解决方案早就有了: Void 。
void是什么?
在ECMAScript规范,有如下描述:
11.4.2 The void Operator
The production UnaryExpression : void UnaryExpression is evaluated as follows:
1.Let expr be the result of evaluating UnaryExpression.
2.Call GetValue(expr).
3.Return undefined.
NOTE:GetValue must be called even though its value is not used because it may have observable side-effects.
总结下:void 运算符能对给定的表达式进行求值,无论void后的表达式是什么,void操作符都会返回undefined.
void 0; //undefined
void (1+2+3) //undefined
void '我不是undefined' //undefined
所以我们利用void的特性, 用void 0 将 undefined 代替掉。但是为什么要用void 0 而不是void ‘我不是undefined’,因为void 0是字节数最少的表达式。
void其他作用?
void除了取undefined外,相信小伙伴们肯定在其他地方也见过,废话不多说,上代码:
<a href="javascript:void (0);"></a>
是不是很熟悉,当a标签href为空时点击触发会默认打开本页面,重新刷新一次页面。这是a标签的默认行为,href="javascript:void (0);"可以很好的阻止a标签的默认行为。
写到最后
上面void描述有一句提示我们要特别看一下:
NOTE:GetValue must be called even though its value is not used because it may have observable side-effects.
大概意思:意思就是无论void右边的表达式是什么,都要对其求值,否则会有副作用。
我们来看代码:
void 1 + 2; //NaN
当void右侧是一个表达式,因为void和+运算符的优先级都是一样的,从右到左运算,void 0 结果是undefined, undefined + 2 结果就是NaN。所以如果右侧是一个表达式,我们应该用()将其优先运算。
void (1 + 2); //undefined
总结
现在很多的打包工具都会将undefined替换成void 0,在查看源码的时候也是经常能看到void 0的,所以大家可以将自己项目代码中残存的undefined换成void 0了。