17道题让你彻底理解JS中的类型转换(2)

Number('123') // 显示类型转换 + '123' // 隐式类型转换 123 != "456" // 隐式类型转换 4 > "5" // 隐式类型转换 5 / null // 隐式类型转换 true | 0 // 隐式类型转换

接下来看一下原始类型显示转换 number 类型会发生什么

Number(null) // 0 Number(undefined) // NaN Number(true) // 1 Number(false) // 0 Number(" 12 ") // 12 Number("-12.34") // -12.34 Number("\n") // 0 Number(" 12s ") // NaN Number(123) // 123

当将一个字符串转换为一个数字时,引擎首先删除前尾空格、\n、\t 字符,如果被修剪的字符串不成为一个有效的数字,则返回 NaN。如果字符串为空,则返回 0。

Number() 方法对于 null 和 undefined 的处理是不同的, null 会转换为 0, undefined 会转换为 NaN

不管是显式还是隐式转换都不能将 Symbol 类型转为 number 类型,当试图这样操作时,会抛出错误。

Number(Symbol('my symbol')) // TypeError is thrown +Symbol('123') // TypeError is thrown

这里有 2 个特殊的规则需要记住:

1、当将 == 应用于 null 或 undefined 时,不会发生数值转换。null 只等于 null 或  undefined,不等于其他任何值。

null == 0 // false, null is not converted to 0 null == null // true undefined == undefined // true null == undefined // true undefined == 0 // false

2、NaN 不等于任何值,包括它自己

NaN === NaN // false if(value !== value) { console.log('the value is NaN') }

object 类型转换

到这里我们已经深入了解了原始类型的转换,接下来我们来看一下 object 类型的转换。

当涉及到对象的操作比如:[1] + [2,3],引擎首先会尝试将 object 类型转为原始类型,然后在将原始类型转为最终需要的类型,而且仍然只有 3 种类型的转换:number, string, boolean

最简单的情况是 boolean 类型的转换,任何非原始类型总是会转换成 true,无论对象或数组是否为空。

对象通过内部 [[ToPrimitive]] 方法转换为原始类型,该方法负责数字和字符串转换。

[[ToPrimitive]] 方法接受两个参数一个输入值和一个需要转换的类型(Numer or String)

number 和 string的转换都使用了对象的两个方法: valueOf 和 toString。这两个方法都在 Object.prototype 上被声明,因此可用于任何派生类,比如 Date, Array等。

通常上 [[ToPrimitive]] 算法如下:

如果输入的值已经是原始类型,直接返回这个值。

输入的值调用 toString() 方法,如果结果是原始类型,则返回。

输入的值调用 valueOf() 方法,如果结果是原始类型,则返回。

如果上面 3 个步骤之后,转换后的值仍然不是原始类型,则抛出 TypeError 错误。

number 类型的转换首先会调用 valueOf() 方法,如果不是原始值在调用 toString() 方法。 string 类型的转换则相反。

大多数 JS 内置对象类型的 valueOf() 返回这个对象本身,其结果经常被忽略,因为它不是一个原始类型。所以大多数情况下当 object 需要转换成 number 或 string 类型时最终都调用了 toString() 方法。

当运算符不同时,[[ToPrimitive]] 方法接受的转换类型参数也不相同。当存在 == 或者 + 运算符时一般会先触发 number 类型的转换再触发 string 类型转换。

在 JS 中你可以通过重写对象的 toString 和 valueOf 方法来修改对象到原始类型转换的逻辑。

答案解析

接下来我们按照之前的转换逻辑来解释一下每一道题,看一下是否和你的答案一样。

true + false // 1

'+' 运算符会触发 number 类型转换对于 true 和 false

12 / '6' // 2

算数运算符会把字符串 ‘6' 转为 number 类型

"number" + 15 + 3 // "number153"

'+' 运算符按从左到右的顺序的执行,所以优先执行 “number” + 15, 把 15 转为 string 类型,得到 “number15” 然后同理执行 “number15” + 3

15 + 3 + "number" // "18number"

15 + 3 先执行,运算符两边都是 number 类型 ,不用转换,然后执行 18 + “number” 最终得到 “18number”

[1] > null // true ==> '1' > 0 ==> 1 > 0 ==> true

比较运算符 > 执行 number 类型隐式转换。

"foo" + + "bar" // "fooNaN" ==> "foo" + (+"bar") ==> "foo" + NaN ==> "fooNaN"

一元 + 运算符比二元 + 运算符具有更高的优先级。所以 + bar表达式先求值。一元加号执行字符串“bar” 的 number 类型转换。因为字符串不代表一个有效的数字,所以结果是NaN。在第二步中,计算表达式'foo' + NaN。

'true' == true // false ==> NaN == 1 ==> false 'false' == false // false ==> NaN == 0 ==> false

== 运算符执行 number 类型转换,'true' 转换为 NaN, boolean 类型 true 转换为 1

null == '' // false

null 不等于任何值除了 null 和 undefined

!!"false" == !!"true" // true ==> true == true ==> true

!! 运算符将字符串 'true' 和 'false' 转为 boolean 类型 true, 因为不是空字符串,然后两边都是 boolean 型不在执行隐式转换操作。

['x'] == 'x' // true

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/f116d2ab68d2169acfe3429f815493f0.html