在工作生涯中,我发现还是有很多很多Frontend Developer(前端程序猿)都不是很清楚Javascript(JS)里有一些基础的知识。这期我们就说说JS里的==
运输和转换规则。
看起来很笨对吧,==
运算符不就是检查其两个操作数是否相等,返回一个布尔值(boolean)结果嘛。
来我们看看下面这个题例:
if( a == 1 && a == 2 && a == 3 ) {
console.log("恭喜你突破0.1了。");
}
现在我要你把上面的if statement成立,从而打印出恭喜你突破0.1了。
,你能办到吗?
要解这道题你就要彻底的了解在JS里的==
运输和转换规则。
在mdn文档有详细说明了规则,我知道很多程序猿都是很懒惰读文档,这里我就做点简介好让你跟容易理解。
我大致总结了一下,按以下规则步骤从1.
到5.
依序做比较,直到得到确切的结果为止:
- 两边相同的类型做比较,就比较值。
- 其中一个是
NaN
,直接返回false
。 -
null
和undefined
只有与自身,或互相比较才会返回true
。 - 两边不同的类型但都是基础类型,转换成数字重复步骤
1.
比较。 - 一边是原始类型,一边是对象,把对象转换成基础类型后重复步骤
1.比较
。
很简明对吧,现在我们就一步一步看。
第一步: 两边相同的类型做比较,就比较值。
这个很好理解吧,应该不用多解释。
就是1 == 1
是true
,"andy" == "cooker"
是false
。
这里有一点要注意以下,如果两边是对象,比较值是怎样呢?在JS里,变量里存的是对象的地址。这里比较值的意思比较两个变量的地址值是不是一样。
第二步:其中一个是NaN
,直接返回false
。
这个也很好理解,就一看到NaN
就直接返回false
。
第三步:null
和undefined
只有与自身,或互相比较才会返回true
。
这个我就直接举例吧:
null == null // true
null == undefined // true
undefined == undefined // true
null == 0 // false
null == NaN // false
第四步:两边不同的类型但都是基础类型,转换成数字重复步骤1.
比较。
如果两边类型不同又是基础类型,比如1 == true
,1
是Number
,true
是Boolean
就把,true转为Number
进行比较。
(1 == true)
+true // 转为Number, 是1
1 == 1 // 就是true
(1 == 'a')
+'a' // 转为Number, 是NaN
1 == NaN // 就是false
(2 == '2')
+'2' // 转为Number, 是2
2 == 2 // 就是true
第五步:一边是原始类型,一边是对象,把对象转换成基础类型后重复步骤1.比较
。
这个的关键在如何把对象转换成基础类型,这里有3个步骤:
-
如果对象有
@@toPrimitive
方法,就调用做比较。如果方法返回不是基础类型,抛出异常。
const a = { // 如果对象有@@toPrimitive方法,就会被调用 [Symbol.toPrimitive](){ return 1; } }
-
调用
valueOf
方法做比较,如果返回值不是基础类型,继续下一步。在JS里,所有对象默认都有valueOf
方法,那么这个方法返回的是什么?默认情况下是返回对象本身。这个valueOf
方法是可以自行更改的:
const a = { valueOf() { return 1; // 更改成返回1 } }
调用
toString
方法作比较,如果方法返回不是基础类型,抛出异常。
知道了第五步的规则逻辑后,我们再来接这个题是不是容易很多了。
我们再看会这个题:
( a == 1 && a == 2 && a == 3 )
我们就只要确保a
能再做比较时依序返回1
,2
和3
就可以了,那么我们可以用任何一个@@toPrimitive
,valueOf
或 toString
来完成。
这里我就用valueOf来做演示:
const a = {
count: 1,
valueOf() {
return this.count++;
}
}
if( a == 1 && a == 2 && a == 3) {
console.log("恭喜你突破0.1了。");
}
去运行看看吧。
其实这个题并不是那么重要,关键是你得理解JS的基础,在JS里等号是如何运算的。
Happy Coding.
Top comments (0)