null VS undefined
“null与undefined的区别?”
以前去淘宝面试的时候被问过这个问题,当时只是粗略的按照犀牛书上的答案讲了下,但具体的并没有深入去了解。
后来有机会去问问身边做JS开发的同事,也没有几个能说清楚的,但是经过问一些JS大牛(斐斐、玉伯),一语惊醒梦中人,先卖个关子,“一语”到最后再总结。下面先来分别了解下null和undefined:
null
来看下书上的解释:Javascript的关键字null是一个特殊的值,它表示“无值”。null常常被看作对象类型的一个特殊值,即代表“无对象”的值。null是个独一无二的值,有别于其他所有的值,如果一个变量的值为null,那么就说明它的值不是有效的对象、数组、数字、字符串和布尔值。当null用户布尔环境,它转换为false。当它用于一个数字环境,它转换为0.当它用于一个字符串环境,它转换为“null”。
恩,这段话读了N久,很容易能从中获取的信息只是null是object类型,我们alert(typeof null)就知道了。但加粗的这段文字“如果一个变量的值为null,那么就说明它的值不是有效的对象、数组、数字、字符串和布尔值”—真的比较难理解:如果一个变量的值为null,可是我并不想做这个假设,我希望知道的是什么情况下会返回null?又或者什么情况下会用到null?
我在问问斐斐这个问题时,她给了我其中一个答案:在DOM选择时,如果选择不到元素(即选择的元素为空)时,返回null:
1
|
alert(doucment.getElementById( 'xxxx' )) |
在控制台输入以上代码,点运行,会发现返回null,也就这样返回了null的值,其实从这个我们很容易总结出:当我们访问一个不存在的对象时,会返回null!
我们在读jQuery等一些JS框架源码的时候经常会看到null的赋值:data=null; 将一个变量设为null是起什么作用呢?
1
2
3
4
5
|
var a = {a1:1,a2:2,a3:3} alert(a) a= null ; b= new a(); alert(b); |
我们运行这段代码,第一次alert的是“[object object]”(请参考犀牛书P118),第二次alert的是什么呢?—第二次会出错“TypeError: a is not a constructor”。这时它返回了错误信息,说a不是一个构造函数! 我 们在第一次alert了之后尝试性的将a设为了null,然后再去实例化a,发现a不是一个构造函数了。
备注:感谢继风的指出,上面这段结论是错的,即使不给a设为null,也是返回错误
如果要将一个标识符声明成object类型,但是暂时不给他实例,那么就可以将它先初始化为null,以便以后使用。
这个大家可以联想到delete,delete可以删除指定的对象的属性、数组元素或变量,但用var语句申明的用户定义变量是不可以被删除的 (参考犀牛书P87)。但设为null却可以,恩。就是这么简单。但JS中的内存回收是可以由垃圾收集(参考犀牛书P63)自动处理的,所以不太需要太操心显式地释放内存。TIPS:但如果用到了闭包可能就释放不了了。
undefined
undefined是window对象的一个属性,它不像null是Javascript的关键字,它不是一个关键字!恩,但从ECMAScript v3标准开始,规定了名为undefined的全局变量,它的初始值是undefined。因此在符合ECMAScript v3的Javascript的实现中,可以把undefined作为关键字处理,只要不给该变量赋值即可,
alert(typeof null)返回的是object,那么undefined会是什么类型呢?答案是undefined,恩就是这么规定的。什么情况下会返回undefined?来看下面几种情况:
- 直接访问没有修改的全局变量undefined。这条就不多说了,直接访问undefined肯定是返回undefined了。
- 访问设置为
undefined
值的变量。将变量的值设置为undefined,返回变量,很明显,肯定是undefined了 使用一个并没有申明的变量(犀牛书P45) 这一条我持怀疑态度,经本人测试,在alert并未申明的变量时,返回的不是undefined,而是出错!这个在《Javascript高级程序设计》一书中也提到了(P3-21)。这条欢迎讨论- 已经申明但没有赋值
12
var
a;
alert(a)
运行这段代码,很显然返回了undefined
- 使用了一个并不存在的对象的属性。一定要注意,这里是对象的属性,不是普通的变量神马的!
1
alert(window.xxxx)
以上代码试图使用window的xxxx属性,但实际上window对象并没有这个属性,所以这时也返回了undefined
以上几条未全,有时你在控制台输入一个函数,但没有任何显式的调用或者输出的话,这时也会返回undefined,其他欢迎补充。
第二条中提到了,我们有时会把变量的值设为undefined,为什么要设为undefined?当我们需要清空一个变量的值的时候就可以用undefined,恩,但是变量还在,值没了。
有时代码中会出现这样的代码:
1
|
typeof a === "undefined" |
这个代码的作用其实就是先判断一下这个变量是否未定义!如果返回true,那么就说明这个变量定义了。
我们在学习一些前端JS框架的过程中,会发现作者会常常自定义一个局部的undefined变量,这是为什么呢?这就要谈到关于提高 undefined性能方面的话题了,首先正如我们上面所分析的,undefined 是全局对象(window)的属性,那么当我们在程序中使用 undefined 值时,实际上使用的是window对象的undefined属性,那么当我们将一个变量或值与undefined进行比较时,javascript引擎会 遍历window所有的属性,直到找到名为’undefined’的属性为止,然后再比较两个操作数的引用指针是否一样。也就是说在遍历属性的过程中会花 费大量的时间,毕竟window对象的属性值非常的多嘛。这样,当频繁与undefined进行比较时,可能就会存在一个性能问题点了。因此,在这种情况 下,我们可以通过自定义个局部的undefined变量,来提高对undefined的比较速度。
例如:
function myFunc() { var undefined; if(x == undefined){…} }
正如上面代码所示,定义undefined局部变量时,其初始值是对window.undefined属性值的引用。在后面代码段中比较操作时,都 是在函数的作用域上进行比较的,由于函数作用域上的变量数量远远少于window对象上的属性个数,那么可想而知比较速度会得到一定提升了。
null与undefined的比较
关键字 | 类型 | 初始值 | 何时用 | |
---|---|---|---|---|
null | 是 | object | null | 引用为空时(如对象) |
undefined | ECMA V3+是 | undefined | undefined | 数值为空时(如普通变量) |
最后玉伯的一语惊醒梦中人:值类型的“虚无”,用 undefined。引用类型的“虚无”,用 null.
这2个东西很难搞,业界讨论的也不多,大家都是浅显的理解,恩,本篇文章并不详细,只是希望能够大家一起讨论,因为会用到,如果不搞清楚,很难写出很好的代码。