1.一直以来的认知
在我学习js的过程中,爱民老师的绿皮书里将js的类型系统分成了两类:
其一是元类型系统:由typeof运算来检测
其二是对象类型系统:是元类型的object的一个分支
而null这个关键字也被归类到了对象类型系统里面了:
- 是属于对象系统的
- 对象是空值
所以,当我们使用typeof去考察Null的话,会返回给我们"object"。
如果去用for(... in null)的方式试图去枚举Null里面的属性的时候。ES5会先行判断null和undefined,如果是这两个值的话,不会去执行循环体。
而我认为这一切都是null既无属性也无方法导致的。而且null也并无原型,也并不是Object()构造器或者其子类实例而来的。
而我是c#出身的前端,我觉得将null归类到对象系统里面是一个不错的选择!
2.《你不知道的js》里面怎么说的?
当我看到第三章的对象的时候,里面有这样一段话
null 有时会被当作一种对象类型,但是这其实只是语言本身的一个 bug,即对 null 执行
typeof null 时会返回字符串 "object"。实际上,null 本身是基本类型
看到这里,完全颠覆我的认知啊!
按照“u dot know”里面的划分的话其实也是书里面很常见的一种划分方式。高程3中就是这样来划分js的类型系统的。但是,因为我觉得爱民老师这样的划分方式也没什么不妥。一切都是看待问题的角度不同导致的。而爱民老师将null归类到对象类型里面去,因为在js中除了undefined之外的都是对象。
而“u dot know”直接耳提面命的告诉我:你一直理解的js类型系统,是错的!
//'u dot kown'里的注解
注 1:原理是这样的,不同的对象在底层都表示为二进制,在 JavaScript 中二进制前三位都为 0 的话会被判
断为 object 类型,null 的二进制表示是全 0,自然前三位也是 0,所以执行 typeof 时会返回“object”。
3.到底怎么理解?
因为有了疑虑,所以我们要去探查真相!
终于,贺老给了我们一个很好的回答!
hax主要说了以下几个点:
- 爱民老师是按照自己的理解来分类的,而不是按照ECMA来照本宣科的,况且他写书的时候ES5/ES6还没有出来,而ES5之前的ES规范其实都写得比较烂
- 现在比较普遍的认知是,typeof null返回“object”是一个历史错误(JS的发明者Brendan Eich自己也是这样说的),只是因为要保持语言的兼容性而维持至今。从ES5制定开始就有动议将typeof null改为返回“null”(如启动node加上“--harmony_typeof”参数,即是如此),但是当前ES6标准草案仍然维持了原样。
- 按照爱民的意见,也可在某种程度上理解为null实为object类型的一个特殊值。在诸如Java这样的语言中,一个变量若是primitive类型,均不可赋以null值,而若是 object,则均可赋以null值。因为在理解上来说,null实际是引用(reference)的特殊值(表示没有指向任何实际对象)
- ECMA是如何划分概念,主要是依据ECMA的逻辑,而不是其他标准。所以从ECMA的逻辑看,类型系统是这样划分的,也是合理的
4.结论
古人常云:尽信书不如无书。书中的知识也是作者按照自己对语言了解的深度和他自己涉猎的广度的一个综合的体现。
而我们看书,其实就是和作者交流的过程。
所以,你说爱民老师说的对吗?
对也不对!狭义的看,如果按照ECMA来说,就不对。但是,广义的看,如果你觉得按照爱民老师的划分,让你对js的类型系统保持了你对“对象”一贯的理解,那就是对的。
那你说,ECMA是对的吗?
对也不对!狭义的看,标准一般都是对的。但是,广义的看,如果你觉得把null不归为对象系统,不符合你对高级语言的认知,那也可以说是不对。
那么,回到我这篇文章的标题,js中的null,你觉得是对象吗?
我可能并不会去正面回答我提出的问题了,但是,我想说的是,至少我现在并不会对于"u dot know"里面说到的这个问题而耿耿于怀了!