Skip to content

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

@lessfish

Description

@lessfish
Owner

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

Activity

itsmatthu

itsmatthu commented on May 23, 2016

@itsmatthu

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

lessfish

lessfish commented on May 23, 2016

@lessfish
OwnerAuthor

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

idda

idda commented on Jun 22, 2016

@idda

蛮好,加油

juemin90

juemin90 commented on Jul 25, 2016

@juemin90

已关注,加油po主

lessfish

lessfish commented on Jul 25, 2016

@lessfish
OwnerAuthor

@juemin90 多谢支持!

jiapeiyang

jiapeiyang commented on Aug 11, 2016

@jiapeiyang

长见识了,谢谢楼主

lessfish

lessfish commented on Aug 11, 2016

@lessfish
OwnerAuthor

@jiapeiyang 感谢支持~

Wangbaogang

Wangbaogang commented on Sep 6, 2016

@Wangbaogang

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

lessfish

lessfish commented on Sep 6, 2016

@lessfish
OwnerAuthor

@Wangbaogang thanks a lot!

lcoder

lcoder commented on Sep 11, 2016

@lcoder

lz棒棒哒

38 remaining items

pq1949

pq1949 commented on May 9, 2018

@pq1949

为什么不用 null 代替 void 0

delayk

delayk commented on May 9, 2018

@delayk

@pq1949 null与undefined等价吗?

eventhorizon-cli

eventhorizon-cli commented on May 9, 2018

@eventhorizon-cli

@delayk
null == undefined
null !== undefined

delayk

delayk commented on May 9, 2018

@delayk

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

eventhorizon-cli

eventhorizon-cli commented on May 9, 2018

@eventhorizon-cli

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

delayk

delayk commented on May 9, 2018

@delayk

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

attraction11

attraction11 commented on Jun 27, 2018

@attraction11

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

pluscai

pluscai commented on Apr 11, 2019

@pluscai

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

wshuhd

wshuhd commented on Nov 8, 2019

@wshuhd

好了好了,star了

HomyeeKing

HomyeeKing commented on Nov 30, 2020

@HomyeeKing

let a = 1
void a+1//NaN

MBRjun

MBRjun commented on Apr 23, 2023

@MBRjun

刚才去试了下在线 JS 压缩工具(基于 UglifyJS 3),发现

  • true > !0
  • false > !1
  • null > null
  • undefined > void 0
xr-betty

xr-betty commented on Apr 23, 2023

@xr-betty
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @waitinghope@delayk@xyyie@juemin90@itsmatthu

        Issue actions

          为什么用「void 0」代替「undefined」 · Issue #1 · lessfish/underscore-analysis