JS中的“==”和“===”的区别

  • 前言:

在同类型变量的比较中,"==="会直接返回true,而非同类型中,"=="直接会先将两个比较值转换为同一类型,再进行比较。

这里的转换就是"隐式转换",例如,以下几种:

"1" ==  1;            // true
1 == "1";             // true
0 == false;           // true

那下面这个怎么解释?

![] == []
//还有下面 a
= [] a == !a && a == a //true

  大部分教程和书中,都建议使用"===",而不建议使用"==",因为"==="可以比年不同类型变量之间的比较,而且速度会更快。但是,我们还是应该搞清楚"=="存在的原理,并进行合理的使用。

  • "=="作用规则

当要比较的值类型相同,值为true,不同即为false。

来看下,值类型不相同的。

MDN文档中,有几条规则:

1、 当数字与字符串进行比较时,会尝试将字符串转换为数字值;

2、如果操作数之一是Boolean,则将布尔操作数转化为1 或 0;

3、 如果操作数之一是对象,另一个数字后字符串,会尝试使用对象的valueOf()和toString()方法讲对象转换为数字或字符串;

4、 null == undefined 为true,此外通常情况下null和undefined与其他对象都不相等。

"![] == []",就相当于"false == []",然后由Boolean操作数,还可以转换为"0 == []" ,而"[]"转换为数字是0,所以返回true。

  • 对象中的valueOf和toString,转换的时候那个优先级高

对象在隐式转换的时候,会尝试调用valueOf 和 toString函数,向字符串或者数字转换。那优先会采用哪一个函数的值?

实验:

const a = {}
a.valueOf = () => 1
a.toString = () => 2
console.log(a == 1, a == 2) // true, false

const b = {}
b.valueOf = () => null // 优先级高于toString,比较直接返回false
b.toString = () => '1'
console.log(b == 'null', b == 1, b == '1') // false, false, false

const c = {}
c.valueOf = () => ([]) // 返回非基本值,将尝试取toString比较
c.toString = () => '1'
console.log(c == 'undefined', c == '1') // false, true

const d = {}
d.valueOf = () => ([]) // 返回非基本值
d.toString = () => ([])
console.log(d == 'undefined', d == '1') // 比较报错:不能转为原始值

经过以上测试,valueOf 的优先级高于toString的优先级,而且valueOf和toString都会返回原始值(“String”,“Number”,“Boolean”,“null”,“undefined”),如果返回的是“null”或者是“undefined”,比较返回false,否则根据另一个比较值转为字符串或者数字进行比较;如果都不返回原始值,则比较操作将会报错。

  • 显式转换

objA == 'abc' 的比较并不同于简单地将objA显式转换为字符串进行比较,即:objA == 'abc' 与 String(objeA) == 'abc' 结果并不一定相同(显式转换直接走toString):

const e = {}
e.valueOf = () => 1
e.toString = () => '2'
console.log(e == 1, e == '1', String(e) == '1',  String(e) == '2') // true, true, false, true
  • ES6中更高优先级的转换函数:Symbol.toPrimitive属性

Symbol.toPrimitive是一个内置的 Symbol 值,它是作为对象的函数值属性存在的,当一个对象转换为对应的原始值时,会调用此函数。该函数被调用时,会被传递一个字符串参数 hint ,表示要转换到的原始值的预期类型。 hint 参数的取值是 "number""string" 和 "default" 中的任意一个。对于”==“操作符,hint传递的值是”default“。

const a = {}
a[Symbol.toPrimitive] = (hint) => {
    if (hint == 'number') return 1
    if (hint == 'string') return 2
    return 3
}
a.valueOf = () => 4
a.toString = () => 5
console.log(a == 1, a == 2, a == 3, a == 4, a == 5) // false, false, true, false, false

如果使用Number或者String强制转换a,则传入的”hint“会是”number“或者”string“。