javaScript中有很多异于常人思维的逻辑,比如null > 0, null == 0都为false,但null >= 0 却为true。


(资料图)

前言

javaScript中有很多异于常人思维的逻辑,比如null > 0,null == 0都为false,但null >= 0却为true。

有些人看到这里觉得这怎么可能,于是跑到浏览器控制台尝试执行了一番,执行后的结果,让自己大吃一惊。

心想自己可能因为这个写了不少bug,今天又学到了一个知识点,但这你要不去了解它的执行原理,估计你怎么都想不通。

下面我们就尝试去一探究竟吧!

ToPrimitive 算法

JavaScript 对象转换到基本类型值时,会使用 ToPrimitive 算法,这是一个内部算法,是编程语言在内部执行时遵循的一套规则。

hint

ToPrimitive 算法在执行时,会被传递一个参数hint,表示这是一个什么类型的运算(也可以叫运算的期望值),根据这个hint参数,ToPrimitive 算法来决定内部的执行逻辑。

hint参数的取值只能是下列 3 者之一:

stringnumberdefault

toPrimitive转换规则

如果传入参数是string,也就是对象到字符串的转换」,经过了如下步骤:

如果对象中有toString()方法,则调用这个方法。如果它返回一个原始值(undefined、Boolean、Number、String、BigInt、Symbol 和 null),js将这个值转换为字符串(如果本身不是字符串的话),并返回这个字符串结果。如果对象没有toString()方法,或者toString()没有返回一个原始值,那么js会调用valueOf()方法。如果返回值是原始值,js将这个值转换为字符串,并返回字符串结果。否则,js抛出一个类型错误异常。

「如果传入参数是number/default,也就是对象到数字的转换」,经过了如下步骤:

和上面有点不同,到数字的转换会先尝试使用valueOf()方法

如果对象具有valueOf()方法,后者返回一个原始值,则js会将其转换为数字(如果需要的话)并返回这个数字。否则,如果对象具有toString()方法,返回一个原始值(字符串直接量),则js将其转换为数字类型,并返回这个数字。否则,js抛出一个类型错误异常。

抽象关系比较算法

调用 b 的 ToPrimitive(hit Number) 方法.调用 a 的 ToPrimitive(hit Number) 方法.如果此时 Result(1) 与 Result(2) 都是字符串,跳到步骤 16.调用 ToNumber(Result(1)).调用 ToNumber(Result(2)).如果 Result(4) 为 NaN, return undefined.如果 Result(5) 为 NaN, return undefined.如果 Result(4) 和 Result(5) 是相同的数字,return false.如果 Result(4) 为 +0, Result(5) 为 -0, return false.如果 Result(4) 为 -0, Result(5) 为 +0, return false.如果 Result(4) 为 +∞, return false.如果 Result(5) 为 +∞, return true.如果 Result(5) 为 -∞, return false.如果 Result(4) 为 -∞, return true.如果 Result(4) 的数值大小小于 Result(5),return true,否则 return false.如果 Result(2) 是 Result(1) 的前缀 return false. (比如 “ab” 是 “abc” 的前缀)如果 Result(1) 是 Result(2) 的前缀, return true.找到一个位置 k,使得 a[k] 与 b[k] 不相等.取 m 为 a[k] 字符的数值.取 n 为 b[k] 字符的数值.如果 m < n, return true,否则 return false.

判断null>0

按照上面这个步骤,我们可以尝试来判断一下null>0的结果

首先第一二步就是为它们分别调用ToPrimitive()将这两个值转换为原始类型,由于这两个值都是基本类型,所以他们转换后还是本身

然后第三步就不适用,我们接着看第四五步,将两个值都转为Number类型,null转换成了+0,而0还是0。

接着看六七,由于两者都不是NaN,所以我们直接看第八步,在js中+0与0是一样的,所以返回false

null > 0 // falsenull < 0 // false

抽象相等比较算法

如果 a 与 b 的类型相同,则:如果 Type(b) 为 undefined,return true.如果 Type(b) 为 null,return true.如果 Type(b) 为 number,则:如果 b 为 NaN,return false.如果 a 为 NaN,return false.如果 a 与 b 数值相同,return true.如果 a 为 +0,b 为 -0,return true.如果 a 为 -0,b 为 +0,return true.否则 return false.如果 Type(b) 为 string,且 a 与 b 是完全相同的字符串,return true,否则 return false.如果 Type(b) 是 boolean,如果都是 true 或 false,return true,否则 return false.如果 a 与 b 是同一个对象引用,return true,否则 return false.如果 a 为 null,b 为 undefined,return true.如果 a 为 undefined,b 为 null,return true.如果 Type(a) 为 number,Type(b) 为 string,返回 a == ToNumber(b) 的结果.如果 Type(a) 为 string,Type(b) 为 number,返回 ToNumber(a) == b 的结果.如果 Type(a) 为 boolean,返回 ToNumber(a) == b 的结果.如果 Type(b) 为 boolean,返回 a == ToNumber(b) 的结果.如果 Type(a) 是 string 或 number,且 Type(b) 是对象类型,返回 a == ToPrimitive(b) 的结果.如果 Type(a) 是对象类型,且 Type(b) 是 string 或 number,返回 ToPrimitive(a) == b 的结果.否则 return false.

判断null==0

null == 0 // false

null == 0 走到了第 10 步,返回了默认的false。

大于等于操作符>=

从常理上来讲,如果null>0为false,null==0也为false,那么null>=0肯定也为false。但事实并非如此

javascript 是这么定义大于等于判断的:

如果 a < b 为false,则 a >= b 为true

这个规则是不是有点逆于常人思维,但它却又是合理的,当a=b肯定就为true对吧

所以null>=0为true,是因为null<0为false,看到这里,是不是又恍然大悟了呢?

推荐内容