拒绝使用undefined!!!

325 阅读3分钟

在日常工作中,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了。

个人博客地址,有兴趣的可以看一看