JS中null和undefined的关系详解,超级透彻

182 阅读3分钟

1. 语义理解

null:空值
undefined:未定义
从字面意思上我们可能并不好区分这二者的区别,你可以记住这句话null是人为赋值的而undefined是代码赋予的原始状态。

undefined的几种情况

  • 变量未初始化
let test;
console.log(test); //undefined
  • 访问对象上不存在的属性
let obj = {};
console.log(obj.a);//undefined
  • 访问本应有但不存的值
function fn(a){
	console.log(a);
}
let b = fn(); //undefined
console.log(b);//undefined

函数fn本应传入一个参数a,但此时未传入就是,undefined,函数本应返回一个值,但未返回,就是undefined

null的几种情况

  • 对象垃圾回收 当一个对象我们不再使用,我们想要把他回收时我们可以使用null
let obj = {
	a: 1
}
let obj = null;
  • 函数返回值含义为空时 比如我们想定义一个函数,返回一个数组中大于0的数,如果不存在满足条件的数我们就可以返回null
function select(arr) {
    let ans = [];
    for (let value of arr) {
        if (value > 0) {
            ans.push(value);
        }
    }
    if(ans.length == 0) return null;
    return ans;
}

2. null == undefined真 null === undefined假

在js中对于相等的判断流程是这样的,两个操作数都会先进行类型转换,然后再比较它们。
转换过程遵循以下规则(其实都是调用valueOf和toString方法)

  1. 如果一个操作数是布尔值,则将布尔值转化为数值0或1
  2. 如果是字符串和数值比较,则将字符串转化为数值
  3. 如果是对象和其余类型比较,则调用对象valueOf()方法

所以null和undefined相等是因为二者都是假值吗?
当然不是,因为null和undefined根本就没有valueOf方法.

console.log(null == false); //false
console.log(null == 0); //false
console.log(undefined == false); //false
console.log(undefined == 0); //false
console.log(undefined == null); //true

console.log(null.valueOf()); //Cannot read property 'valueOf' of null
console.log(undefined.valueof()); //Cannot read property 'valueOf' of null

所以二者相等仅仅是因为在语言设计时,设计者觉得二者很像,才使他们相等。
但实际上我们并不应该混用二者,在第一节的语义部分已经提到过二者的语义是有差别的。

3. 补充小知识(不要再把null和object混为一谈)

console.log(typeof(undefined)); //undefined
console.log(typeof(null));  //object

对于undefined没有什么争议,但null到底是对象吗?
很多人说null是一种特殊的对象,我认为这种说法是错误的。
从上面的介绍中我们已经可以看到null是没有valueOf方法的,所以其根本就没有链接到Object.prototype的原型链。我们可以用另一种方法准确查看其类型

console.log(Object.prototype.toString.call(null));      //[object Null]
console.log(Object.prototype.toString.call(undefined)); //[object Undefined]

所以null就是Null类型,和Object没关系。至于为什么typeOf为什么会返回object,其实是底层代码的一些误判导致的,这里就不做详细说明了。