从0 == ''
说JavaScript隐性转换
比较篇
关系运算符的隐性转换
规则如下:
-
NaN
做>
、<
、==
运算时,结果恒为false
。做!=
运算时,结果恒为true
。// false console.log(0 > NaN); // false console.log(0 < NaN); // false console.log(0 == NaN); // false console.log(NaN == NaN); // true console.log(0 != NaN); // true console.log(NaN != NaN);
-
null
与undefined
比较,结果如下。// true console.log(undefined == undefined); // true console.log(null == undefined); // true console.log(null == null);
-
如果两边都是字符串,从左到右,将每个字符使用
char.charCodeAt()
转换为unicode
编码依次比较。// true console.log("2" > "10"); // 等价于 console.log("2".charCodeAt() > "10".charCodeAt()); // 50 console.log("2".charCodeAt()); // 49 console.log("10".charCodeAt()); /* 先判断第一项的第一个字符'2'的charCodeAt()值与第二项的第一个字符'1'的charCodeAt()值,'2'的charCodeAt()值大, 则第一项大 */ // true console.log("abc" > "a"); /* 先判断第一项的第一个字符'a'的charCodeAt()值与第二项的第一个字符'a'的charCodeAt()值,相等。 第二个比较项没有字符可比较了。 则第一项大。 */ // true console.log("abc" > "aac"); /* 先判断第一项的第一个字符'a'的charCodeAt()值与第二项的第一个字符'a'的charCodeAt()值,相等。 再判断第一项的第二个字符'b'的charCodeAt()值与第二项的第二个字符'a'的charCodeAt()值, 'b'的charCodeAt()值大。 则第一项大。 */
-
如果有一边为基础类型,将两边都转为
number
再进行比较。如果是基础类型,则直接使用Number()
进行转换。如果是数组或者对象,则会先调用valueOf()
方法获取原始值。如果返回值为基础类型,按照基础类型规则比较。否则使用toString()
转为字符串再进行比较。// true console.log(0 == "");
回到最初的起点,现在来看这个一切都迎刃而解。
当
0
与''
比较时,会先使用Number('')
把''
转换为数字,而Number('')
的结果正好是0
。所以0 == ''
在简单的情况下
// false console.log(0 > "abc"); // 数字与基础类型数据比较,使用Number()把非数字类型数据转为数字再进行比较 // NaN console.log(Number('abc')); // 返回结果是NaN,NaN与任何比较都为false // false console.log(2 > "10"); // 数字与基础类型数据比较,使用Number()把非数字类型数据转为数字再进行比较 // 10 console.log(Number('10')); // 2不大于10,所以结果为false
如果比较数据是高级数据类型(Array,Object)
var obj = { num: 1, str: 'str' }; var arr = [1, 2, 3, 4]; // true console.log(obj == '[object Object]') // [object Object] console.log(obj.valueOf().toString()) // true console.log(arr == '1,2,3,4') // 1,2,3,4 console.log(arr.valueOf().toString()) var arr2 = [10] // false console.log(arr > 11) // '10' console.log(arr.valueOf().toString()) // false console.log('10' > 11) /* 在高级数据类型比较时,先使用valueOf()获取原始值,如果是高级类型再使用toString()转为字符串。 之后再按照基础类型比较规则比较 */
我们已经知道高级类型比较时,会先调用
valueOf()
方法,如果是高级类型再调用toString()
。那么如果我们重写这两个方法呢?var a = { valueOf: function() { return '2'; } }; var b = { toString: function() { return 2; } }; // true console.log(a > '10') // ↓ console.log(a.valueOf() > '10') // ↓ console.log('2' > '10') // false console.log(b > '10') // ↓ console.log(b.valueOf() > '10') // ↓ console.log(2 > '10') // ↓ console.log(2 > Number('10'))
www