起因
某天,在看某位同学的js代码,代码中发现了一个奇怪的东西 void 0,虽然第一眼看不懂这是什么东西,但是根据上下文,这里应该是想判断是否等于undefined,为什么要这样写的,有什么渊源吗?顺便就把undefined和null都拿出来复习了一下.
介绍
undefined和null是js中类型七种数据类型,这两种数据的区别是
- undefined是声明了未定义
- null是一个空指针,除非定义为null,否则不会出现null
null
null是有一些奇怪的地方,例如常见的面试题
typeof null 为什么是object?
这道题目在我一开始学习js的时候就接触过,说是js设计的一个bug啦,只是因为旧代码太多,怕改正过来会造成影响,所以一直保持,也有的说这是一个空指针,空对象,所以为object.但是我总觉得这样说服力不够,于是我上网翻了一些资料
在 javascript 的最初版本中,使用的 32 位系统,并且底层都表示为2进制,为了性能考虑使用低位存储了变量的类型信息:
000:对象
1:整数
010:浮点数
100:字符串
110:布尔
全部为0: null
所以typeof就是利用这一机制去判断的,所以null全部为0就复合了对象的000,所以被判断为object
并且还有个注意点
null == undefined //true null和undefined用==比较结果是true,并且没有发生隐式转换,就是true
复制代码
undefined
接下来就是undefined了,这个设计感觉也有个非常大的bug,那么重要的东西,竟然不是一个关键字,竟然是一个变量.一个变量意味着什么,你可以随意更改它啊!!
所以有的程序员就会利用void 0去代替undefined,鬼知道原来的undefined会不会被某个阴险小人替换了.
那么void 0到底是怎么来的?
根据ECMAScript,void后面接什么都是undefined,也有的说void 0 是从其他语言带过来的习惯,是一种老司机的写法,所以下次我们要用到undefined的时候就要void 0代替,这样比较显得老司机
undefined什么情况下会被替换?
这里我自己测试了一下
- 在谷歌浏览器69.0.3497.100版本下
var undefined = 2;console.log(undefined); //undefined
复制代码
结果是undefined,也就是在新版的谷歌浏览器里面的全局作用域下面是无法更改undefined的
//这次改用constconst undefined = 2; //Identifier 'undefined' has already been declaredconsole.log(undefined);
复制代码
用const则会报错,已经declared了,let也同样
- 那就试试ie浏览器吧(IE11)
var undefined = 2;console.log(undefined); //undefined
复制代码
这样的结果还是undefined,所以在ie11的全局作用域下面也不能替换
- 直到ie8版本的浏览器发生了变化
var undefined = 2;console.log(undefined); //2
复制代码
竟然改变了,ie8的全局作用域下是可以改变undefined的
这样看来好像也没什么用是不是?ie8很多公司都不用去兼容了,慢着
- 在谷歌浏览器69.0.3497.100版本下,我们试试在函数作用域下
(function () {var undefined = 2console.log(undefined); //2 })()
复制代码
发现这样就改变了undefined
(function () {const undefined = 2console.log(undefined); //2})()
复制代码
const同样可行,并且在ie的11,10,9,8几个版本中,无一例外的,undefined都被覆盖了
为什么会这样呢?
这时候想到,在全局作用域下,全局变量会变成window上面的一个属性,这时候我们查查看这个属性有什么特别不就知道原因了
console.log(Object.getOwnPropertyDescriptor(window, undefined)); //{value: undefined, writable: false, enumerable: false, configurable: false}
复制代码
这时候拿到数据属性可以看到,不可重写,不可枚举,不可改变特征值或者被删除,所以在全局作用域下面是不可以被重写的.
那ie8呢?为什么可以?
console.log(Object.getOwnPropertyDescriptor(window, undefined)); //{configurable: false, enumerable: false, value: undefined, writable: true}
复制代码
ie8同样,不可枚举,不可删除或修改特征值,但是!!可以被重写!!所以ie8的全局作用域上面是可以被重写的!!
结论:虽然undefined在现在主流的绝大部分浏览器的全局作用域上面都是不能更改了,但是在函数作用域或者块级作用域下面还是能被重写的,当然绝大部分人应该都不会去干这种傻事,但是还是用viod 0吧,这样可以以防万一,同时也更像一个老司机的代码啊