console.log(null == false);
开门见山,说出你的答案! 对,没错,答案是false
! 让我们一探究竟吧!
规定
先来阅读以下两份规则:
严格相等 === :
全等操作符比较两个值是否相等,两个被比较的值在比较前都不进行隐式转换。如果两个被比较的值具有不同的类型,这两个值是不全等的。否则,如果两个被比较的值类型相同,值也相同,并且都不是 number 类型时,两个值全等。最后,如果两个值都是 number 类型,当两个都不是 NaN,并且数值相同,或是两个值分别为 +0 和 -0 时,两个值被认为是全等的。
var num = 0;var obj = new String("0");var str = "0";var b = false;console.log(num === num); // trueconsole.log(obj === obj); // trueconsole.log(str === str); // trueconsole.log(num === obj); // falseconsole.log(num === str); // falseconsole.log(obj === str); // falseconsole.log(null === undefined); // falseconsole.log(obj === null); // falseconsole.log(obj === undefined); // false复制代码
相等运算== :
The comparison x == y, where x and y are values, produces true or false.
- 如果x不是正常值(比如抛出一个错误),中断执行。
- 如果y不是正常值,中断执行。
- 如果Type(x)与Type(y)相同,执行严格相等运算x === y。
- 如果x是null,y是undefined,返回true。
- 如果x是undefined,y是null,返回true。
- 如果Type(x)是数值,Type(y)是字符串,返回x == ToNumber(y)的结果。
- 如果Type(x)是字符串,Type(y)是数值,返回ToNumber(x) == y的结果。
- 如果Type(x)是布尔值,返回ToNumber(x) == y的结果。
- 如果Type(y)是布尔值,返回x == ToNumber(y)的结果。
- 如果Type(x)是字符串或数值或Symbol值,Type(y)是对象,返回x == ToPrimitive(y)的结果。
- 如果Type(x)是对象,Type(y)是字符串或数值或Symbol值,返回ToPrimitive(x) == y的结果。
- return false。
那么我们提炼以下规则:
- 如果 x或者y不是正常值,中断执行。
- 如果 typeof x 和typeof y相同,执行x === y。
- 如果 x和y分别是null和undefined,返回true。
- 如果 x和y分别是数值和字符串类型,那么返回 x == Number(y) (y 为字符串)
- 如果 x和y其中一个为布尔类型,那么返回x == Number(y) (若 x 为布尔类型)
- 如果 x和y分别是(Symbol值 或 数值 或 字符串) 和 对象,返回x == ToPrimitive(y) (若 y 为对象)
- return false
1、将值转为原始值,ToPrimitive()。
2、将值转为数字,ToNumber()。
3、将值转为字符串,ToString()。
1.ToPrimitive()
js引擎内部的抽象操作ToPrimitive有着这样的签名: ToPrimitive(input, PreferredType?) input是要转换的值,PreferredType是可选参数,可以是Number或String类型。他只是一个转换标志,转化后的结果并不一定是这个参数所值的类型,但是转换结果一定是一个原始值(或者报错)。
1.1如果PreferredType被标记为Number,则会进行下面的操作流程来转换输入的值。
1、如果输入的值已经是一个原始值,则直接返回它2、否则,如果输入的值是一个对象,则调用该对象的valueOf()方法, 如果valueOf()方法的返回值是一个原始值,则返回这个原始值。3、否则,调用这个对象的toString()方法,如果toString()方法返回的是一个原始值,则返回这个原始值。4、否则,抛出TypeError异常。复制代码
1.2如果PreferredType被标记为String,则会进行下面的操作流程来转换输入的值。
1、如果输入的值已经是一个原始值,则直接返回它2、否则,调用这个对象的toString()方法,如果toString()方法返回的是一个原始值,则返回这个原始值。3、否则,如果输入的值是一个对象,则调用该对象的valueOf()方法, 如果valueOf()方法的返回值是一个原始值,则返回这个原始值。4、否则,抛出TypeError异常。复制代码
既然PreferredType是可选参数,那么如果没有这个参数时,怎么转换呢?PreferredType的值会按照这样的规则来自动设置:
1、该对象为Date类型,则PreferredType被设置为String2、否则,PreferredType被设置为Number复制代码
toString()
和 valueOf()
的用法有待补充。
2.ToNumber()
根据参数类型进行下面转换:
参数 | 结果 |
---|---|
undefined | NaN |
null | +0 |
布尔值 | true转换1,false转换为+0 |
数字 | 无须转换 |
字符串 | 有字符串解析为数字,例如:‘324’转换为324,‘qwer’转换为NaN |
对象 | 先进行 ToPrimitive(obj, Number)转换得到原始值,在进行ToNumber转换为数字 |
3.ToString()
根据参数类型进行下面转换:
参数 | 结果 |
---|---|
undefined | 'undefined' |
null | 'null' |
布尔值 | 转换为'true' 或 'false' |
数字 | 数字转换字符串,比如:1.765转为'1.765' |
字符串 | 无须转换 |
对象 | 先进行 ToPrimitive(obj, String)转换得到原始值,在进行ToString转换为字符串 |
Object.is():
Object.is()
判断两个值是否相同。如果下列任何一项成立,则两个值相同:
- 两个值都是 undefined
- 两个值都是 null
- 两个值都是 true 或者都是 false
- 两个值是由相同个数的字符按照相同的顺序组成的字符串
- 两个值指向同一个对象
- 两个值都是数字并且
- 都是正零 +0
- 都是负零 -0
- 都是 NaN
- 都是除零和 NaN 外的其它同一个数字
这种相等性判断逻辑和传统的 ==
运算符所用的不同,==
运算符会对它两边的操作数做隐式类型转换(如果它们类型不同),然后才进行相等性比较,(所以才会有类似 "" == false
为 true
的现象),但 Object.is
不会做这种类型转换。
这与===
运算符也不一样。===
运算符(和==
运算符)将数字值-0
和+0
视为相等,并认为Number.NaN
不等于NaN
。 示例:
Object.is('foo', 'foo'); // trueObject.is(window, window); // trueObject.is('foo', 'bar'); // falseObject.is([], []); // falsevar test = { a: 1 };Object.is(test, test); // trueObject.is(null, null); // true// 特例Object.is(0, -0); // falseObject.is(-0, -0); // trueObject.is(NaN, 0/0); // true复制代码
实际运用
我们先看以下以下几种值比较的结果:
挑选重点来分析如下:
①
[1,2] == "1,2" //true复制代码
左边数组类型为Obeject
,右边是String
,满足总结条件6。 执行ToPrimitive([1,2])
,在没有参数的情况下且不为Date
类型,转换类型自动为Number
再执行 [1,2].valueOf()
,类型还是Obeject
,不为原始值 再执行[1,2].toString()
,"1,2"
为字符串原始值 最后比较"1,2" == "1,2"
,返回true
②
开始的那个问题:
null == false; //false复制代码
因为false
是Boolean类型,满足总结中的第五条,所以实际比较
Number(bull) == false;0 == null;//false复制代码
最新的 ECMAScript 标准定义了 7 种数据类型: 6 种 原始类型: Boolean Null Undefined Number String Symbol (ECMAScript 6 新定义) 和 Object
0 == null
null的类型是Null
,实际上这个比较不满足转换的任何一条规则,所以返回false
。
③
0 == NaN; //false复制代码
两边都是Number
类型,所以比较全等===
返回false
NaN == NaN; //false复制代码
从数值的角度上讲NaN
不与任何值相等。