void 和 undefined

993 阅读2分钟

一道挖坑面试题

突然想到了一个给面试者挖坑的面试题:

以下代码的运行结果是:

(undefined = 42) && console.log(undefined)

1) 报错
2) 无输出
3) 输出 42
4) 输出 undefined

解释这题之前,先来介绍下怎么想到它的。

void 0

这一切起源于,void 0

如果我们观察ts、bable的转换结果或者一些js库,我们会发现在需要使用undefined的部分大都使用了void 0

直到昨天,我才去了解了下void 0是个啥,然后发现真有意思。

首先,void 0结果就是undefined,但是代码长度上稍短一些。然后呢,undefined在js里并不是关键字之类的,它只是window上的一个属性。

void有两种形式,一个是空格加参数,一个就是括号,它接收一个参数,但不管这个参数是啥,都返回undefined

void 0
void 42
void 'hello world'
void void 0
void(void(0))

是的,以上都是undefined

undefined

然后呢,如刚才说的,undefined不是关键词,它是window上的一个属性,所以一下代码都可以运行:

undefined = 42;
window.undefined = 42;
var undefined = 42; // let和const则不行,因为undefined已经存在了

以上代码虽然都不会报错,但是我们会发现undefined还是undefined

原因也很简单:

Object.getOwnPropertyDescriptor(window, 'undefined');
// {value: undefined, writable: false, enumerable: false, configurable: false}

没错,这玩意儿是不可写的。

void 0的用途

但是呢,既然它不是关键子,那挡不住声明个变量叫这名字啊:

(function() {
	const undefined = 42;
    console.log(undefined); // 42
})();

其实不少js库都有这样的代码:

(function(self, undefined) {
  ...
})(window);

这里直接把undefined搞成了局部变量,这样用它时就不是从window上去取了。

所以呢,为了有闭包把undefined给改了,还是使用void 0方便些。

除此之外,void还可以给iife使用:

void function() {
	console.log(42);
}();

面试题解答

最后解答一下开头说到的面试题。

首先,它不会报错。

然后呢,赋值表达式的值是右值,所以虽然undefined的值不会被改掉,但console.log是会执行的。

所以答案就是输出undefined啦。

最后,感谢大家浪费时间学习这些并不是太有用的知识。