JavaScript 是弱类型语言,这就意味着,等于操作符会为了比较两个值而进行强制类型转换。
"" == "0" // false
0 == "" // true
0 == "0" // true
false == "false" // false
false == "0" // true
false == undefined // false
false == null // false
null == undefined // true
" \t\r\n" == 0 // true
上面的表格展示了强制类型转换,这也是使用 == 被广泛认为是不好编程习惯的主要原因, 由于它的复杂转换规则,会导致难以跟踪的问题。
此外,强制类型转换也会带来性能消耗,比如一个字符串为了和一个数字进行比较,必须事先被强制转换为数字。
严格等于操作符
严格等于操作符由三个等号组成:===
不像普通的等于操作符,严格等于操作符不会进行强制类型转换。
"" === "0" // false
0 === "" // false
0 === "0" // false
false === "false" // false
false === "0" // false
false === undefined // false
false === null // false
null === undefined // false
" \t\r\n" === 0 // false
上面的结果更加清晰并有利于代码的分析。如果两个操作数类型不同就肯定不相等也有助于性能的提升。
比较对象
虽然 == 和 === 操作符都是等于操作符,但是当其中有一个操作数为对象时,行为就不同了。
{} === {}; // false
new String('foo') === 'foo'; // false
new Number(10) === 10; // false
var foo = {};
foo === foo; // true
这里等于操作符比较的不是值是否相等,而是是否属于同一个身份;也就是说,只有对象的同一个实例才被认为是相等的。
比较规则
先说 ===,这个比较简单。下面的规则用来判断两个值是否===相等:
- 如果类型不同,就[不相等]。
- 如果两个都是数值,并且是同一个值,那么[相等]的是,如果其中至少一个是NaN,那么[不相等]。(判断一个值是否是NaN,只能用isNaN()来判断)。
- 如果两个都是字符串,每个位置的字符都一样,那么[相等];否则[不相等]。
- 如果两个值都是true,或者都是false,那么[相等]。
- 如果两个值都引用同一个对象或函数,那么[相等];否则[不相等]。
- 如果两个值都是null,或者都是undefined,那么[相等]。
再说 ==,根据以下规则:
- 如果两个值类型相同,进行 === 比较。
- 如果两个值类型不同,他们可能相等。根据下面规则进行类型转换再比较:
- 如果一个是null、一个是undefined,那么[相等]。
- 如果一个是字符串,一个是数值,把字符串转换成数值再进行比较。
- 如果任一值是 true,把它转换成 1 再比较;如果任一值是 false,把它转换成 0 再比较。
- 如果一个是对象,另一个是数值或字符串,把对象转换成基础类型的值再比较。对象转换成基础类型,利用它的toString或者valueOf方法。 js核心内置类,会尝试valueOf先于toString;例外的是Date,Date利用的是toString转换。
- 任何其他组合,都[不相等]。
值类型 == 值类型 => 相当于 Number(值类型) == Number(值类型)。
引用类型 == 值类型 => 对象转化成原始类型的值,再进行比较。
比较规则:数组与数值进行比较,会先转成数值,再进行比较;与字符串进行比较,会先转成字符串,再进行比较;与布尔值进行比较,两个运算子都会先转成数值,然后再进行比较。
这里来解析一道题目 [] == ![] ,下面是这个表达式为何为 true 的步骤:
// [] 转成 true,然后取反变成 false
[] == false
// 相当于,Number([])为0,Number(false)为0
0 == 0 // => true
网友评论