Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

为什么用「void 0」代替「undefined」 #1

Open
lessfish opened this issue May 16, 2016 · 56 comments
Open

为什么用「void 0」代替「undefined」 #1

lessfish opened this issue May 16, 2016 · 56 comments
Labels

Comments

@lessfish
Copy link
Owner

@lessfish lessfish commented May 16, 2016

Why underscore

最近开始看 underscore源码,并将 underscore源码解读 放在了我的 2016计划 中。

阅读一些著名框架类库的源码,就好像和一个个大师对话,你会学到很多。为什么是 underscore?最主要的原因是 underscore 简短精悍(约 1.5k 行),封装了 100 多个有用的方法,耦合度低,非常适合逐个方法阅读,适合楼主这样的 JavaScript 初学者。从中,你不仅可以学到用 void 0 代替 undefined 避免 undefined 被重写等一些小技巧 ,也可以学到变量类型判断、函数节流&函数去抖等常用的方法,还可以学到很多浏览器兼容的 hack,更可以学到作者的整体设计思路以及 API 设计的原理(向后兼容)。

之后楼主会写一系列的文章跟大家分享在源码阅读中学习到的知识。

欢迎围观~ (如果有兴趣,欢迎 star & watch~)您的关注是楼主继续写作的动力

Why does void 0 replace undefined

说来惭愧,underscore 源码解读这个 Repo 放在 Github 都已经 20 天没有更新了,要不是今天 "不小心" 注意到,我居然都快忘了(是不是 lu 多了),所以今晚无论如何都要 lu 出第一篇(毕竟万事开头难)。相对于其他源码解读的文章,基本都会从整体设计开始讲起,楼主觉得 underscore 这个库有点特殊,so 决定按照自己的思路,从用 void 0 代替 undefined 说起。

underscore 源码没有出现 undefined(注意,其实有出现一处,是为 "undefined",而不是 undefined),而用 void 0 代替之。为什么要这么做?我们可以从两部分解读,其一是 undefined 哪里不好了,你非得找个替代品?其二就是替代品为毛要找 void 0?

我们先看第一点,答案很简单,undefined 并不是保留词(reserved word),它只是全局对象的一个属性,在低版本 IE 中能被重写。

var undefined = 10;

// undefined -- chrome
// 10 -- IE 8
alert(undefined);

事实上,undefined 在 ES5 中已经是全局对象的一个只读(read-only)属性了,它不能被重写。但是在局部作用域中,还是可以被重写的。

(function() {
  var undefined = 10;

  // 10 -- chrome
  alert(undefined);
})();

(function() {
  undefined = 10;

  // undefined -- chrome
  alert(undefined);
})();

接下来思考第二个问题,为毛找的替代品是 void 0?

我们来看看 MDN 的解释:

The void operator evaluates the given expression and then returns undefined.

意思是说 void 运算符能对给定的表达式进行求值,然后返回 undefined。也就是说,void 后面你随便跟上一个表达式,返回的都是 undefined,都能完美代替 undefined!那么,这其中最短的是什么呢?毫无疑问就是 void 0 了。其实用 void 1,void (1+1),void (0) 或者 void "hello",void (new Date()) 等等,都是一样的效果。更重要的前提是,void 是不能被重写的(cannot be overidden)。

那么,ES5 大环境下,void 0 就没有用武之地了吗?答案是否定的,用 void 0 代替 undefined 能节省不少字节的大小,事实上,不少 JavaScript 压缩工具在压缩过程中,正是将 undefined 用 void 0 代替掉了。

一篇不长的文章写了两个小时,心累,不点个赞、不关注下楼主的 Repo 你觉得好意思吗?https://github.com/hanzichi/underscore-analysis

Read More

@lessfish lessfish added the bug label May 21, 2016
@itsmatthu

This comment has been minimized.

Copy link

@itsmatthu itsmatthu commented May 23, 2016

不小心走进了楼主的博客,我很欣赏楼主对于库的解读和学习。我自己也在学习和使用过程中。这篇文章显得有些虎头蛇尾了,较大的篇幅解读了undefined是可以被重写,但是对于为什么能减少字节,压缩工具的实现,居然一句话带过了,这样显得结尾有些草率和仓促了,继续努力

@lessfish

This comment has been minimized.

Copy link
Owner Author

@lessfish lessfish commented May 23, 2016

谢谢。
可能我们的重点不同吧,至于压缩工具的实现,这似乎有点 "偏题" 了,反正我是这么认为的~

@lessfish lessfish closed this May 23, 2016
@lessfish lessfish reopened this May 23, 2016
@idda

This comment has been minimized.

Copy link

@idda idda commented Jun 22, 2016

蛮好,加油

@juemin90

This comment has been minimized.

Copy link

@juemin90 juemin90 commented Jul 25, 2016

已关注,加油po主

@lessfish

This comment has been minimized.

Copy link
Owner Author

@lessfish lessfish commented Jul 25, 2016

@juemin90 多谢支持!

@jiapeiyang

This comment has been minimized.

Copy link

@jiapeiyang jiapeiyang commented Aug 11, 2016

长见识了,谢谢楼主

@lessfish

This comment has been minimized.

Copy link
Owner Author

@lessfish lessfish commented Aug 11, 2016

@jiapeiyang 感谢支持~

@Wangbaogang

This comment has been minimized.

Copy link

@Wangbaogang Wangbaogang commented Sep 6, 2016

支持支持!最近在读underscore源码,楼主的注释版读起来很棒!

@lessfish

This comment has been minimized.

Copy link
Owner Author

@lessfish lessfish commented Sep 6, 2016

@Wangbaogang thanks a lot!

@lcoder

This comment has been minimized.

Copy link

@lcoder lcoder commented Sep 11, 2016

lz棒棒哒

@git-lt

This comment has been minimized.

Copy link

@git-lt git-lt commented Sep 19, 2016

写的不错

@zhw2590582

This comment has been minimized.

Copy link

@zhw2590582 zhw2590582 commented Sep 28, 2016

这个系列,我看定了

@Melody12ab

This comment has been minimized.

Copy link

@Melody12ab Melody12ab commented Oct 13, 2016

已start,楼主加油!!!

1 similar comment
@snayan

This comment has been minimized.

Copy link

@snayan snayan commented Oct 14, 2016

已start,楼主加油!!!

@lessfish lessfish changed the title 为什么用 `void 0` 代替 `undefined` 为什么用「void 0」代替「undefined」 Oct 18, 2016
@cleartime

This comment has been minimized.

Copy link

@cleartime cleartime commented Nov 3, 2016

已start,楼主加油!!!

@waitinghope

This comment has been minimized.

Copy link

@waitinghope waitinghope commented Nov 9, 2016

你不知道的js中卷,2.4.2也谈到了void 0
同时举的例子我觉得不太好。

@lessfish

This comment has been minimized.

Copy link
Owner Author

@lessfish lessfish commented Nov 10, 2016

@waitinghope 谢谢指出。没看过「你不知道的js」,不介意的话举个更好的例子?我可以补充或者修改下

@waitinghope

This comment has been minimized.

Copy link

@waitinghope waitinghope commented Nov 10, 2016

@hanzichi 给你的outlook发了封信.

@lessfish

This comment has been minimized.

Copy link
Owner Author

@lessfish lessfish commented Nov 10, 2016

@waitinghope 看完了,其实他的意思就是「void + 任何数字」返回的都是 undefined。如果在一个函数中又要执行一个定时器,又要 return,写成 return void setTimeout(...) 的形式,不失为一种 hack

https://book.douban.com/review/8163708/ 他说的不对吧,如果 App.ready 了,那么就会返回 result 值了,如果 !App.ready ,那么返回的是 undefined

@waitinghope

This comment has been minimized.

Copy link

@waitinghope waitinghope commented Nov 10, 2016

我觉得他的意思是:var t; 然后return t;
这个时候if(t)是判断不出来啥的.

@lessfish

This comment has been minimized.

Copy link
Owner Author

@lessfish lessfish commented Nov 10, 2016

@waitinghope 理解有出入吧 ...

@xyyie

This comment has been minimized.

Copy link

@xyyie xyyie commented Nov 11, 2016

来看看分析的,还是赞下。

@LastKing

This comment has been minimized.

Copy link

@LastKing LastKing commented Dec 2, 2016

0.0 重点是写出来了,但是 感觉好头重尾轻。。。不过还是 理解。。!!点个赞赞!

@MontageD

This comment has been minimized.

Copy link

@MontageD MontageD commented Dec 23, 2016

看出分析很用心,值得学习。

@Sy-52

This comment has been minimized.

Copy link

@Sy-52 Sy-52 commented Jan 15, 2017

楼主你好,首先向你的分享行为与辛勤劳作表示敬意。
我在读完本文后发现其中一点写的有点问题,在此提出,如果理解的有问题,希望楼主赐教。

(function() {
var undefined = 10;

// 10 -- chrome
alert(undefined);
})();

第一,这一句中undefined在其中起的是变量标识符的作用,我觉得这种情况下说 ' 用void 0 替代undefined去做变量名更好"没有任何意义。
第二、我感觉楼主文章中,这段想表达的意思是这种情况是个Bug,但我认为这种情况是标识符解析的规则导致。如果你想在函数作用域中正确返回undefined的话,避免使用undefined做变量标识符不是更好?或者你也可以返回window.undefined。

@lessfish

This comment has been minimized.

Copy link
Owner Author

@lessfish lessfish commented Jan 15, 2017

@Sy-52 因为你知道 避免使用 undefined,但是别人可能不知道(虽然我们一般不会这么做),但是确实在低版本 IE 下 undefined 能被作为变量标识符而被重写但不报错

@Sy-52

This comment has been minimized.

Copy link

@Sy-52 Sy-52 commented Jan 16, 2017

@LastKing 多谢指教,对java等语言不是很熟悉,没研究过,很长姿势。对于你说的第二点:

if(xxx ==undefined) 他是比对 变量还是 比对 js的本身的数据类型undefined 勒?。。。

经我测试,xxx对比的是函数作用域中的变量undefined,这也符合标识符解析规则。

@hanzichi 又想了一下,我可能get到你的意思了。

(function() {
var undefined = 10;

// 10 -- chrome
alert(undefined);
})();

一、你的意思可能是:如果你想在函数作用域中返回或操作系统属性undefined,但如果你在函数作用域中定义有名为undefined变量,你就无法如愿,所以此时用void 0替代undefined更好:

(function() {
var undefined = 10;

alert(void 0);
})();

二、但在全局作用域中:

var undefined = 10;

// undefined -- chrome
// 10 -- IE 8
alert(undefined);

你本来在全局作用域中定义一个名为undefined的变量赋值为10,但在操作它时却被系统属性undefined覆盖,这个才是不符初衷吧,这里用void 0替换undefined没有意义。(另外我测试IE8下alert(undefined)显示为undefined)

综上,由于其他语言中undefined是保留字@LastKing,那么这里提示大家养成不使用undefined做变量名的习惯不是比用void 0替换undefined更好?(因为以后undefined可能会成为保留字)

@waitinghope

This comment has been minimized.

Copy link

@waitinghope waitinghope commented Jan 16, 2017

@Sy-52 https://book.douban.com/subject/26606848/
最关键的是你的code运行在一个不知道undefined是不是真正的undefined的环境中。
这一点对于underscore特别重要。
举个类似的例子,你怎么确定自己拿到的$就是jQuery的$?如果不是,那你所有依赖$的code还能用吗?

@lessfish

This comment has been minimized.

Copy link
Owner Author

@lessfish lessfish commented Jan 16, 2017

@Sy-52 我觉得你有点钻牛角尖了,私以为 get 到「undefined 在低版本 IE 下能被改写所以采用 void 0 代替」这点就可以了,这也是我的初衷,毕竟 IE8 也即将退出历史舞台。当然,实际开发中,一般不会用 undefined 去做变量名,但是这和知道本文中心点不冲突。

@Sy-52

This comment has been minimized.

Copy link

@Sy-52 Sy-52 commented Jan 16, 2017

@hanzichi ok,捋顺了,感谢你愿意花时间解惑 ^_^

@w-y

This comment has been minimized.

Copy link

@w-y w-y commented Jan 23, 2017

0.._比void 0更短

@lessfish

This comment has been minimized.

Copy link
Owner Author

@lessfish lessfish commented Jan 23, 2017

@w-y 还真是,测了下 IE8 也没有问题,请教下这是什么原理?

@w-y

This comment has been minimized.

Copy link

@w-y w-y commented Jan 23, 2017

@hanzichi 类似 这种 0['x'] 但0.x会语法错误 4个字符的话应该还有几种写法

@lessfish

This comment has been minimized.

Copy link
Owner Author

@lessfish lessfish commented Jan 23, 2017

@w-y 感谢,学习了~

@lcoder

This comment has been minimized.

Copy link

@lcoder lcoder commented Jan 24, 2017

@w-y 为什么我chrome测试:console.log( 0.. ) 报错?

@lessfish

This comment has been minimized.

Copy link
Owner Author

@lessfish lessfish commented Jan 24, 2017

@lcoder 后面还跟了个 _ ,意思就是 0['_']

@luoliqiang luoliqiang mentioned this issue Feb 9, 2017
@195286381

This comment has been minimized.

Copy link

@195286381 195286381 commented Mar 5, 2017

楼主分析的不错 学到新知识

@pageliu16

This comment has been minimized.

Copy link

@pageliu16 pageliu16 commented Aug 22, 2017

谢谢楼主,正在研究中

@wave1992

This comment has been minimized.

Copy link

@wave1992 wave1992 commented Aug 29, 2017

~👍

@district10

This comment has been minimized.

Copy link

@district10 district10 commented Oct 21, 2017

我记得 lodash 里面是用 var undefined 来定义 undefined... 也是奇妙. 自己定义 undefined, 然后不 define 它... 于是就是 undefined.

@WalkerKing

This comment has been minimized.

Copy link

@WalkerKing WalkerKing commented Nov 28, 2017

非常感谢分享,正在看您的注释版的源码

@fxk01

This comment has been minimized.

Copy link

@fxk01 fxk01 commented Feb 2, 2018

写的很好

@shangguanhonglei

This comment has been minimized.

Copy link

@shangguanhonglei shangguanhonglei commented Feb 8, 2018

undefined不是js的保留关键字,所以undefined可以作为变量被赋值,至于为什么使用void 0 ,楼主的解析还是不错的

@sighWang

This comment has been minimized.

Copy link

@sighWang sighWang commented Feb 12, 2018

建议楼主简练下语言,删掉「说来惭愧...」等。这样子读起文章来会更专注

@pq1949

This comment has been minimized.

Copy link

@pq1949 pq1949 commented May 9, 2018

为什么不用 null 代替 void 0

@delayk

This comment has been minimized.

Copy link

@delayk delayk commented May 9, 2018

@pq1949 null与undefined等价吗?

@blurhkh

This comment has been minimized.

Copy link

@blurhkh blurhkh commented May 9, 2018

@delayk
null == undefined
null !== undefined

@delayk

This comment has been minimized.

Copy link

@delayk delayk commented May 9, 2018

@blurhkh ==是做了隐式转换的, null === undefined的结果可是false哦
你可以看下underscore源码里用来判断undefined的地方都是用===而不是==

@blurhkh

This comment has been minimized.

Copy link

@blurhkh blurhkh commented May 9, 2018

@delayk 嗯,我只是说null !== undefined

@delayk

This comment has been minimized.

Copy link

@delayk delayk commented May 9, 2018

@blurhkh 好吧…那你应该回复 @pq1949 而不是回复我

@attraction11

This comment has been minimized.

Copy link

@attraction11 attraction11 commented Jun 27, 2018

看了楼主与大家的讨论很有收获,自己实际测试一下确实如此。在全局作用域中以widow的属性优先,局部作用域中可以实现定义变量。但并不如void 0 字符少 。

@pluscai

This comment has been minimized.

Copy link

@pluscai pluscai commented Apr 11, 2019

今天在看框架时刚好遇到这个,有收货,多谢!

@newitp

This comment has been minimized.

Copy link

@newitp newitp commented Nov 8, 2019

好了好了,star了

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
You can’t perform that action at this time.