9

恩,这是个问题。如果你有印象,void甚至是js中的26个关键字之一,根据ECMA官方标准,它是一个一元操作符,它的唯一作用就是返回一个undefined,不管这个操作符后面传的操作数是什么。
在标准里对void的执行细节是这么说的:

  1. Let expr be the result of evaluating UnaryExpression.--》把表达式的值赋给expr;
  2. Call GetValue(expr).--》调用expr的内部函数获取它的值;
  3. Return undefined. --》返回undefined

这有点像那个很有意思的笑话:

客官你吃啥?
啊,我要一碗牛肉面,面给我多煮会少放点葱多放点辣肉给我放多一点汤给我多盛点。
哦,一碗牛肉面。

void可以像下面这样使用:

javascriptvoid 0;
void "you are useless?";
void false;
void [];
void /(useless)/ig;
void function(){ console.log("you are so useless?"); }
//... always return undefined

后面可以是任何表达式,返回的永远是undefined!很明显,在你想获得undefined的时候,可以用这个操作符。通常有如下使用场景:

一、Javascript URIs

html<a href="javascript:void(0);">
  Click here to do nothing
</a>

<a href="javascript:void(document.body.style.backgroundColor='green');">
  Click here for green background
</a>

这是MDN文档中给出的例子,我之前看到不少远古时代的网页应用这样的写法,就是直接在a标签的href属性里写js代码,比如<a href="javascript:;">link</a>,这样写跟<a href="#">link</a>的区别是后者在点击的时候页面会跳到最顶部去,如果这不是你要的效果一定要注意;在href里写javascript:void(0);则可以避免上述问题。

不过现在这样写javascript:是不提倡的。

二、用于闭包避免解析错误

你们一定已经看到过闭包的这种写法:

javascript!function fn(){
  console.log("I will show immediately.")
}()

上述这段代码中的!可以换成其他操作符,比如+-~,加上这些前缀的作用是避免js解析器讲函数体解析为函数声明。

解析器在遇到代码function fn(){ /*...*/}时会把这解析成函数声明,在函数声明后面再跟着一对括号会产生语法错误,前面加上一个操作符,解析器就会把这段代码当成函数表达式,从而可以顺利执行。

在前面这个场景中,这个操作符也可以用void,效果与上述代码一致。

javascriptvoid function fn(){
  console.log("I will show immediately.")
}()

那么问题是,为什么不直接使用undefined这个值的字面量形式呢?
我在stackoverflow上找到一个解释:
因为undefined既不是保留字,也不是关键字,它可以作为变量标识符赋值,所以你手写出来的undefined有可能被覆盖的!比如:

javascriptvar undefined="oops";
alert(undefined);

上述代码在一些原始社会的浏览器中会成功弹出oops,说到原始社会的浏览器,我们来试试IE吧。经过测试,这段代码在IE9以下的浏览器中真的会弹出oops! oops! 你也可以试试。
不过,在现代浏览器中,已经不能这么做了,仍然可以给undefined赋值,但这个是无效的。试试跟undefined很类似的null,给它赋值就会报错。

所以,当我们要获得真正的undefined值的时候,用void操作符吧。void后面可以是任何操作数(注意:如果后面没有操作数也会报错的),那使用时用什么呢?良心推荐还是写void 0吧,毕竟这是最简短的。

关于数组中的undefined,还有一些很奇怪的地方,比如,如何区分下面这两个数组中的各项是不是相同:

javascriptvar arr1=[1,2,undefined,4];
var arr2=[1,2,,4];
arr1[2]===arr2[2]; //true

下次再说。


oslh
604 声望9 粉丝

王炸裂,Pied Piper CDO(Chief Daza Officer),Bugtags 前端