举个简单的栗子:
A和B两个人肚子都很饿,要去吃饭。A已打电话到饭店预约位置,B则打算下班后考察下再做决定。对于饭店来说,A基本上就是他的客户了,只不过还没见到人来,定为null(毕竟交易还没产生),而对饭店来说,B是谁啊,他们根本没听到过这个人,为undefined
然而,概念还是念叨念叨的
从字面上理解:undefined 不明确的,不知道的,例如var a;我们声明了一个变量但是没有给定初始值,但是这个a代表着啥,boolean? string? number? object? function? 都有可能。而 var a = null;的话,则直接声明了a是有的,但是它的值是空的,没有的,如果把他们同时跟一个数值相加减,也正解释了为啥 3+null = 0 而 3+undefined得到的结果是NaN了。
这俩货是一堆好兄弟,相同而又不同。我们都知道JavaScript几个基本上数据类型:
Boolean、Null Undefined String Number Symbol(ES6新增),这俩货占据两席位置,分量如此重,不得不说,不得不重视起来他们啊。
Undefined 其实代表的是不存在的值,Null是字面量同时也是语言中的关键词,表示无法识别的对象值。他们都没有属性和方法,也不能给其属性赋值。他们的布尔值都是false,说到布尔值为false的,通常包括 NaN 、 0、空字符串、Null 、Undefined 这五种常见的对象。他们之间的关系,可以这样总结:
Null == 0 //false
Undefined == 0 //false
undefined == "" //false
null == "" //false
null == NaN //false
undefined == NaN //false
undefined == null //true
undefined === null //false
null 是一个特殊的“对象”,相当于一个空对象的预期。而undefined就是“未定义”,没有。实际中更加推荐使用null,对他们执行typeof分别是
typeof undefined //undefined
typeof null //object
相似之处
二者是不可变的,都没有自己的属性和方法,如果你试图给他们增加方法或者属性,都会产生类型错误。各自都是孤家寡人,不用拖家带口的,一人吃饱全家不饿。都是“空”的东西
不同点
“类型”不同,undefined代表了一个意想不到的没有的值,null是预期没有值的代表,至于如何区分他们,下文有介绍
何种情况下会产生undefined呢?
当声明一个变量的时候,比如 var a; //undefined
访问不存在的对象的时候 var obj = {a:1}; var c = obj.c; //undefined
当数组中的索引不存在的时候 var arr = [1,2,3]; arr[5]; //undefined
定义一个function,当没有返回值的时候,返回的也是undefined
何种情况下会产生null呢?
当你试图去获取一个不存在的DOM的时候会返回null
程序猿自己return null
说了这么多,那么问题来了,如何区分一个变量究竟是null还是undefined呢?下面为大家提供一个方法以示区分:
Object.prototype.toString.apply(null) // [object Null]
Object.prototype.toString.apply(undefined) // [object Undefined]
做一个延伸(别问我为啥去做这个操作,因为我是神经病)
如果我分别用一个Number String 分别跟 undefined null做加减运算,会产生什么操作呢?
5 + null; //5
5+undefined // NaN
"5" + null ; //"5null"
"5"+undefined; //“5undefined”
'aa'+undefined; //"aaundefined"
'aa'+null; // "aanull"
"aa"*null; //NaN
"aa"*undefined //NaN
题外话:
将我们需要判断类型的东西通过对象的原型toString转换为字符串,简直就是神操作,可以狠轻松的判断很多类型,例如
Object.prototype.toString.call({}) // [object Object]
Object.prototype.toString.call([]) // [object Array]
Object.prototype.toString.call(function d(){}) // [object Function]
Object.prototype.toString.call(123) // [object Number]
Object.prototype.toString.call("123") // [object String]
Object.prototype.toString.call(Symbol()) // [object Symbol]