null == undefined和null === undefined的那些事儿

487 阅读4分钟

ECMAScript有6种简单的数据类型(也称原始类型):UndefinedNullBooleanNumberStringSymbol
还有1种复杂数据类型(也称引用类型):Object,包括对象和函数。
对象和基础值之间的转换,也是高频面试问题。以下主要介绍明着转暗着转的方式。

类型转换:光明正大用方法转

1、基础值转换成对象

通过Object(x)的方式对基础类型进行转换,形成基础值的包装类,对于对象转换返回原对象,不做任何处理。

console.log(Object(1)) // Number {1}
console.log(Object(true)) // Boolean {true}
console.log(Object('test')) // String {'test'}
console.log(Object(undefined)) // {}
console.log(Object(null)) // {}
console.log(Object(Symbol('test'))) // Symbol {Symbol(test), description: 'test'}

2、对象转换成基础值

任何对象都有继承至原型的方法valueof()toString(),是对象转换成值的关键。 对象转换成基础值的方式就是通过valueOf取出内部槽中的[[PrimitiveValue]]

var numberObj = Object(1);
console.log(numberObj.valueOf()); // 1
var booleanObj = Object(true);
console.log(booleanObj.valueOf()); // true
var stringObj = Object('test');
console.log(stringObj.valueOf()); // 'test'
var symbolObj = Object(Symbol('test'));
console.log(symbolObj.valueOf()); // Symbol('test')
var undefinedObj = Object(undefined);
console.log(undefinedObj.valueOf()); // {},因为其没有内部槽[[PrimitiveValue]],所以返回原对象
var nullObj = Object(null);
console.log(nullObj.valueOf()); // {},因为其没有内部槽[[PrimitiveValue]],所以返回原对象

类型转换:偷偷摸摸隐式转换

隐式转换通过两个经典面试进行分析:

题一:null == undefined返回啥?

答案:true

(1)等于和不等于

ECMAScript 中的等于操作符用两个等于号(==)表示,如果操作数相等,则会返回 true。不等于 操作符用叹号和等于号(!=)表示,如果两个操作数不相等,则会返回 true。这两个操作符都会先进 行类型转换(通常称为强制类型转换)再确定操作数是否相等。

  • 如果任一操作数是布尔值,则将其转换为数值再比较是否相等。false 转换为 0true 转换 为 1
console.log(true == 1) // true 相当于:1 == 1
console.log(true == 2) // false 相当于:1 == 2
console.log(false == 0) // true 相当于:0 == 0
console.log(false == 1) // false 相当于:0 == 1
  • 如果一个操作数是字符串,另一个操作数是数值,则尝试将字符串转换为数值,再比较是否相等
console.log(NaN == NaN) // false NaN不等于自己,为false
console.log(NaN != NaN) // true NaN不等于自己,为true
console.log('NaN' == NaN) // false 相当于:NaN == NaN,NaN不等于自己,为false
console.log('NaN' != NaN) // true 相当于:NaN != NaN,NaN不等于自己,为true
  • 如果一个操作数是对象,另一个操作数不是,则调用对象的 valueOf()方法取得其原始值,再 根据前面的规则进行比较
onsole.log(new Object(2) == 2) // true new Object(2)的valueof值为22== 2
console.log(new Object('2') == 2) // true new Object('2')的valueof值为'2''2'== 2根据以上规则为true
console.log(new Object(2) == new Object('2')) // false new Object(2)和new Object('2')都是对象,不进行转换

特殊情况:

  • nullundefined 相等,undefined是由null派生而来的,因此 ECMA-262 将它们定义为表面上相等
  • nullundefined 不能转换为其他类型的值再进行比较
  • 如果有任一操作数是 NaN,则相等操作符返回 false,不相等操作符返回 true
  • 如果两个操作数都是对象,则比较它们是不是同一个对象。如果两个操作数都指向同一个对象,则相等操作符返回 true。否则,两者不相等

(2)全等和不全等

全等和不全等操作符与相等和不相等操作符类似,只不过它们在比较相等时不转换操作数

  • 全等和不全等操作符与相等和不相等操作符类似,只不过它们在比较相等时不转换操作数。全等操作符由 3 个等于号(===)表示,只有两个操作数在不转换的前提下相等才返回 true
  • 不全等操作符用一个叹号和两个等于号(!==)表示,只有两个操作数在不转换的前提下不相等才返回 true

特殊情况:

  • nullundefined 不全等

总结

==中会存在隐式类型转换的情况,主要是利用其valueOf获取内部槽中的[[PrimitiveValue]],如果拿到的值不为基础值,还会通过toString进行转换。