关于null == 0该如何运用?

对着背影说爱祢 提交于 2020-02-26 01:55:33

单纯从这个题目本身来看,没有什么东西,而且这个问题的答案我们通过浏览器就能得到印证。我们今天要说的不是这个问题,而是对于 == 到底是如何运算的?

首先我们来解决这个问题 null == 0 ? 结果是什么呢?我们先通过浏览器来验证一下。

关于null == 0该如何运用?

在这里我们得到的答案,false,是不是今天的文章就结束了呢,显然没有。我们深入的来探究一下,为什么是这样的结果呢。

接下来我们来探究一下,为什么是这样的一个过程!

为了证明一下说明的内容是浏览器 JS 引擎的设置规则,而非个人认为,下面引用 W3C 的制定规范。

以下内容来自 W3C 标准

11.9.3 抽象相等比较法。

比较运算 x==y, 其中 x 和 y 是值,产生 true 或者 false。这样的比较按如下方式进行:

若 Type(x)与 Type(y)相同,则

若 Type(x)为 Undefined, 返回 true。

若 Type(x)为 Null, 返回 true。

若 Type(x)为 Number, 则

若 x 为 NaN, 返回 false。

若 y 为 NaN, 返回 false。

若 x 与 y 为相等数值, 返回 true。

若 x 为 +0 且 y 为−0, 返回 true。

若 x 为 −0 且 y 为+0, 返回 true。

返回 false。

若 Type(x)为 String, 则当 x 和 y 为完全相同的字符序列(长度相等且相同字符在相同位置)时返回 true。 否则, 返回 false。

若 Type(x)为 Boolean, 当 x 和 y 为同为 true 或者同为 false 时返回 true。 否则, 返回 false。

当 x 和 y 为引用同一对象时返回 true。否则,返回 false。

若 x 为 null 且 y 为 undefined, 返回 true。

若 x 为 undefined 且 y 为 null, 返回 true。

若 Type(x) 为 Number 且 Type(y) 为 String ,返回comparison x ==ToNumber(y)的结果。

若Type(x) 为 String 且 Type(y)为 Number,返回比较 ToNumber(x) == y 的结果。

若Type(x)为 Boolean,返回比较 ToNumber(x) == y 的结果。若 Type(y)为 Boolean, 返回比较 x == ToNumber(y)的结果。

若 Type(x) 为 String 或Number ,且Type(y)为Object ,返回比较 x ==ToPrimitive(y)的结果。

若Type(x)为Object 且Type(y)为String 或Number,返回比较ToPrimitive(x)== y 的结果。

不满足上述条件则返回 false。

我们一打眼,看着上面的规则很多。接下来我们根据实际应用层面给大家阐述上面的内容。

这里要说明一下:

这里Type函数并不是typeof,他只能返回基本数据类型(NullUndefinedObject Number String Boolean )

其实==的判断规则分为两大类: 类型相同和不相同

1.类型相同

以下是相等的内容

null == null

undefined == undefined

+0 == -0

true == true

false == false

对象的引用地址相同则相同

字符串完全相同的字符序列(长度相等且相同字符在相同位置)时返回 true。

数字相同则为 true

上面的这些内容都是规定,不存在隐式类型转换。

不满足以上条件的同类型元素的 == 式就是 false

对于 NaN 来说,只要存在 NaN 就一定是 false。

2.类型不同

undefined == null 值为 true 这个是规定,不存在类型转换。

前提是判断 X == Y 时,在类型不同时,采取的规则

当 X, Y 中任意一人是 Boolean 类型时,把 Boolean 类型的转换成数字类型进行判断。

转化规则 true == 1 false == 0

例如:

true == ‘1’

这里先进行 数字化转化得到 true 转化成 1 ,最终比较的是 数字 1 和 字符串的 1。也就是 1 == ‘1’

False == [] 也是一样的根据这条规则转化成 0 == []

在这里大家会经常出现的一个问题?

在我们写代码的过程中可能会产出类似以下的代码

if(a == true) {

// coding

}

很显然这里在我们判断最终的结果是 a == 1,所以可能和大家的预想不一样。推荐大家这样使用:

// 显式使用

if(a) {

// coding

}

// 强制转换

if(!!a) {

// coding

}

// 强制转换

if(Boolean(a)) {

// coding

}

那上面我们保留着一个问题就是 1 == ‘1’ 这个的判断规则是什么啊?

接下来就是字符串与数字的比较了。

当 X Y中一个是数字另一个是字符串,比较规则是把字符转换成数字然后在进行比较。1 == ‘1’ 就是 把 ‘1’ 转换成数字 1 在进行比较。

最后就差一个 Object 的类型比较了。这里我们引入原话

若Type(x)为Object且Type(y)为String或Number,返回比较ToPrimitive(x)== y的结果。

Type(y) 是 Boolean类型,在比较过程中也会被转化成 Number。上面描述的没有问题撒。这里面提到一个toPrimitive(x),抽象操作,规范中是咋说的捏?

9.1

ToPrimitive 运算符接受一个值,和一个可选的 期望类型作参数。ToPrimitive 运算符把其值参数转换为非对象类型。如果对象有能力被转换为不止一种原语类型,可以使用可选的期望类型来暗示那个类型。返回该对象的默认值。对象的默认值由把期望类型传入作为hint 参数调用对象的内部方法[[DefaultValue]]得到,[[DefaultValue]]这个内部方法由 8.12.8 定义。

8.12.8

用字符串 hint 调用 O 的 [[DefaultValue]] 内部方法,采用以下步骤:

令 toString 为用参数 "toString" 调用对象 O 的 [[Get]] 内部方法的结果。如果 IsCallable(toString) 是 true, 则令 str 为用 O 作为 this 值,空参数列表调用 toString 的 [[Call]] 内部方法的结果。如果 str 是原始值,返回 str。令 valueOf 为用参数 "valueOf" 调用对象 O 的 [[Get]] 内部方法的结果。如果 IsCallable(valueOf) 是 true, 则令 val 为用 O 作为 this 值,空参数列表调用 valueOf 的 [[Call]] 内部方法的结果。如果 val 是原始值,返回 val。

抛出一个 TypeError 异常。

当用数字 hint 调用 O 的 [[DefaultValue]] 内部方法,采用以下步骤:

令 valueOf 为用参数 "valueOf" 调用对象 O 的 [[Get]] 内部方法的结果。如 果 IsCallable(valueOf) 是 true, 则令 val 为用 O 作为 this 值,空参数列表调用 valueOf 的 [[Call]] 内部方法的结果。如果 val 是原始值,返回 val。令 toString 为用参数 "toString" 调用对象 O 的 [[Get]] 内部方法的结果。如 果 IsCallable(toString) 是 true, 则令 str 为用 O 作为 this 值,空参数列表调用 toString 的 [[Call]] 内部方法的结果。如果 str 是原始值,返回 str。

抛出一个 TypeError 异常。

当不用 hint 调用 O 的 [[DefaultValue]] 内部方法时,除非 O 是 Date 对象的情况下把hint 当作字符串一样解释它的行为,除此之外把 hint 当作数字一样解释它的行为。

上面说明的 [[DefaultValue]] 在原生对象中只能返回原始值。如果一个宿主对象实现了它自身的 [[DefaultValue]] 内部方法,那么必须确保其 [[DefaultValue]] 内部方法只能返回原始值。

一看到这里,哇塞,这也太多了,我也看不懂啊。其实没那么复杂。

如果是对象的话,先检查是否具有 valueOf 函数,如果有并且返回基本类型值,就使用该值进行强制类型转换

var obj = {

value: '123',

valueOf() {

console.log("valueOf")

return this.value

}

}

console.log(obj == 123)

结果为:

关于null == 0该如何运用?

如果没有 ValueOf,或者 ValueOf 返回的不是原始值。继续寻找 toString 函数

var obj = {

value: '123',

valueOf() {

console.log("valueOf")

return {}

},

toString() {

console.log('toString')

return this.value

}

}

console.log(obj == 123)

结果为:

关于null == 0该如何运用?

那如果 toString 方法返回的也不是基本类型怎么办?

var obj = {

value: '123',

valueOf() {

console.log("valueOf")

return {}

},

toString() {

console.log('toString')

return {}

}

}

console.log(obj == 123)

我们看一下结果

关于null == 0该如何运用?

会报一个错误。所以规范强调,务必返回原始值。

这样的话,对于 == 的抽象规则,回去接着看我们的问题

Null == 0 ?

发现怎么对都对不上,上面的规则,别忘了最后一条。不符合上面规矩的,一律返回false

所以 null == 0 的值是false

总结:

对于上面的内容,除了类型相同不存在隐式类型转换外,是直接比较,还有一个特殊的就是 undefined == null 其他的内容最终都是转换到数字层面进行比较。这么一说相信,同学们都能很好的掌握==

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!