【译】Truth, Equality and JavaScript
原文:Truth, Equality and JavaScript
作为 JavaScript 新手,对下列两种情况可能感到惊恐
1 | if ([0]) { |
1 | if ("potato") { |
好消息是有一个所有浏览器都通用的标准。有些老司机教育你尽量不要用这些。我认为真正的勇士应该敢于面对惨淡的人生,敢于正视淋漓的鲜血…(意译过头了好像😤)
x 为真?x 和 y 相等?关于真假,等价的问题,在 JavaScript 中可以分为三个大块:
- 条件表达式以及操作符:if, && , ||等
- 等于:==
- 严格相等:===
下面就来分情况讨论
条件表达式
在 JavaScript 中,所有的条件表达式和条件操作符遵循同样的规则,这里就直接用if
作为范例
if
条件判断,会将括号中的表达式通过 ToBoolean 将结果转化为 boolean 类型。ToBoolean 在 ES5 spec 中的具体定义如下:
参数类型 | 结果 |
---|---|
Undefined | false |
Null | false |
Boolean | 和输入结果相同(没有转化) |
Number | false: +0, -0, NaN true: 其他 |
String | false:空字符串,长度为 0 true: 其他 |
Object | true |
看一些示例:
1 | var trutheyTester = function (expr) { |
等于(==)
==
是相当宽松的,类型不同的值都有可能相等。因为在进行比较之前,JS 引擎可能将等号左边或右边或两边的操作数转换为同样的类型,然后再进行比较,所谓的隐式类型转换。这也是为啥老司机们不让你使用的原因。
俗话说:逃避是解决不了问题的。你要想掌握一门语言,你就得从里到外全面了解。就算你无视 ==
的存在,你也不可能摆脱 coercion 的的纠缠。在 JavaScript 中 coercion 无处不在。合理使用 coercion 将会给你的编码带来极大的便利。
接下来就瞅瞅 ==
在 ECMA 中是怎么工作的。不要慌张,只需要记住:Undefined
和 Null
相等;以及 JS 为了极速对比效率,大部分情况都会将类型往 Number
转化。详情见下:
Type(x) | Type(y) | Result |
---|---|---|
x,y类型相同 | x,y类型相同 | 同严格相等(===) |
null | Undefined | true |
undefined | null | true |
Number | String | x == toNumber(y) |
String | Number | toNumber(x) == y |
Boolean | (any) | toNumber(x) == y |
(any) | Boolean | x == toNunber(y) |
String Number |
Object | x == toPrimitive(y) |
Object | String Number |
toPrimitive(x) == y |
otherwise… | otherwise… | false |
当结果为表达式的时候,将会继续进行转化,直到结果为 BooleantoNumber
和 toPrimitive
按照以下规则运行:
- toNumber
参数类型 | 结果 |
---|---|
Undefined | NaN |
Null | 0 |
Boolean | true: 1 false: 0 |
Number | 不转化 |
String | “123” => 123 “123a” => NaN “abc” => NaN |
- toPrimitive
参数类型 | 结果 |
---|---|
Object | 先尝试 valueOf(),如果没有定义或者结果不是原始类型,调用 toString(),否则,返回 error |
其他 | 不转化 |
看些示例:
[0] == true
1 | // 等值判定 |
“potato” == true
1 | // 等值判定 |
“potato” == false
1 | // 等值判定 |
object with valueOf
1 | // 等值判定 |
object with toString
1 | var crazyObj = { |
严格相等(===)
这个就比较简单了,类型不同,永远不相等;然后记住:
- object 必须指向同一个对象才相等
- 字符串必须含有相同的字符集才相等
- 其他值必须一样才相等
- NaN, nul, undefined 永远互不相等
- NaN 不等于 NaN
Type(x) | Valuse | Result |
---|---|---|
x,y类型不同 | x,y 类型不同 | false |
Undefined OR Null | Undefined OR Null | true |
Number | x,y 值相同(都不是 NaN) | true |
String | 含有相同字符集 | true |
Boolean | 都为 true 或者 false | true |
Object | x,y 指向同一个对象 | true |
其他 | 其他 | false |
一些过度相等的例子
1 | // unnecessary |
typeof 返回值就是 String 类型,所有待比较的两个值始终是 String,使用 ==
就够了
1 | // unnecessary |
null == undefined
Note: 由于undefined
的变量可能是由于重复定义来的,所以用null
进行判断比较保险
1 | // unnessary |