标签:new 总结 强制类型转换 结果 valueof http nan 类型 ==
类型转换是将值从一种类型转换为另一种类型的过程(比如字符串转数字,对象转布尔值等)
类型转换可以分为隐式类型转换和显式类型转换。
二者的区别显而易见:我们能够从代码中看出哪些地方是显式强制类型转换,而隐式强制类型转换则不那么明显,通常是某些操作产生的副作用。
例如:
var a = 42; var b = a + ""; // 隐式强制类型转换 var c = String( a ); // 显式强制类型转换
对变量 b 而言,强制类型转换是隐式的;由于 + 运算符的其中一个操作数是字符串,所以是字符串拼接操作,结果是数字 42 被强制类型转换为相应的字符串”42“。
而 String() 则是将 a 显示强制类型转换为字符串。
严格相等运算符(===)不会触发类型隐式转换,所以它可以用来比较值和类型是否都相等。
隐式类型转换是一把双刃剑,使用它虽然可以写更少的代码但有时候会出现难以被发现的bug。
在条件判断时,除了 undefined,null,false,NaN,‘ ‘,0,-0,其它所有值都转为 true,包括所有对象。
Boolean() 方法可以用来显式将值转换成 boolean 型。
隐式类型转换通常在逻辑判断或者有逻辑运算符时被触发(|| && !)
Boolean(2) // 显示类型转换 if(2) {} // 逻辑判断触发隐式类型转换 !!2 // 逻辑运算符触发隐式类型转换 2 || ‘hello‘ // 逻辑运算符触发隐式类型转换
String() 方法可以用来显式将值转为字符串,隐式转换通常在有 + 运算符并且有一个操作数是 string 类型时被触发,如:
String(123) // 显式类型转换 123 + ‘‘ // 隐式类型转换
Symbol 类型转 String 类型是比较严格的,它只能被显式的转换
String(Symbol(‘symbol‘)) // ‘Symbol(symbol)‘ ‘‘ + Symbol(‘symbol‘) // TypeError is thrown
和 Boolean()、String() 方法一样, Number() 方法可以用来显式将值转换成 number 类型。
number 的隐式类型转换是比较复杂的,因为它可以在下面多种情况下被触发。
Number(‘123‘) // 显示类型转换 + ‘123‘ // 隐式类型转换 123 != "456" // 隐式类型转换 4 > "5" // 隐式类型转换 5 / null // 隐式类型转换 true | 0 // 隐式类型转换
这里有 2 个特殊的规则需要记住:
null == 0 // false, null is not converted to 0 null == null // true undefined == undefined // true null == undefined // true undefined == 0 // false
NaN === NaN // false
到这里我们已经深入了解了原始类型的转换,接下来我们来看一下对象转原始类型。
对象在转换类型时,会调用内置的 [[ToPrimitive]] 函数,对于该函数来说,算法逻辑一般如下:
当然也可以重写 Symbol.toPrimitive,该方法在转原始类型时调用优先级最高:
let a = { valueOf() { return 0 }, toString() { return ‘1‘ }, [Symbol.toPrimitive]() { return 2 } } 1 + a // => 3
加法运算符不同于其他几个运算符,它有以下两个特点:
1 + ‘1‘ // ‘11‘ true + true // 2 4 + [1,2,3] // "41,2,3"
如果你对于答案有疑问的话,请看解析:
1
转换为字符串,得到结果 ‘11‘
true
转为数字 1
toString
转为字符串 1,2,3
,得到结果 41,2,3
另外对于加法还需要注意这个表达式 ‘a‘ + + ‘b‘
‘a‘ + + ‘b‘ // -> "aNaN"
因为 + ‘b‘
等于 NaN
,所以结果为 "aNaN"
,你可能也会在一些代码中看到过 + ‘1‘
的形式来快速获取 number
类型。
那么对于除了加法的运算符来说,只要其中一方是数字,那么另一方就会被转为数字
4 * ‘3‘ // 12 4 * [] // 0 4 * [1, 2] // NaN
toPrimitive
转换对象unicode
字符索引来比较let a = { valueOf() { return 0 }, toString() { return ‘1‘ } } a > -1 // true
在以上代码中,因为 a
是对象,所以会通过 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
== 运算符对数组类型执行 number 转换,先调用对象的 valueOf() 方法,结果是数组本身,不是原始类型值,所以执行对象的 toString() 方法,得到字符串 ‘x‘
[] + null + 1 // ‘null1‘ ==> ‘‘ + null + 1 ==> ‘null‘ + 1 ==> ‘null1‘
‘+‘ 运算符执行 number 类型转换,先调用对象的 valueOf() 方法,结果是数组本身,不是原始类型值,所以执行对象的 toString() 方法,得到字符串 ‘‘, 接下来执行表达式 ‘‘ + null + 1
0 || "0" && {} // {} ==> (0 || ‘0‘) && {} ==> (false || true) && true ==> true && true ==> true
逻辑运算符 || 和 && 将值转为 boolean 型,但是会返回原始值(不是 boolean)
[1,2,3] == [1,2,3] // false
当运算符两边类型相同时,不会执行类型转换,两个数组的内存地址不一样,所以返回 false
{} + [] + {} + [1] // ‘0[object Object]1‘ ==> +[] + {} + [1] ==> 0 + {} + [1] ==> 0 + ‘[object Object]‘ + ‘1‘ ==> ‘0[object Object]1‘
所有的操作数都不是原始类型,所以会按照从左到右的顺序执行 number 类型的隐式转换, object 和 array 类型的 valueOf() 方法返回它们本身,所以直接忽略,执行 toString() 方法。 这里的技巧是,第一个 {} 不被视为 object,而是块声明语句,因此它被忽略。计算从 +[] 表达式开始,该表达式通过toString()方法转换为空字符串,然后转换为0
! + [] + [] + ![] // ‘truefalse‘ ==> !(+[]) + [] + (![]) ==> !0 + [] + false ==> true + [] + false ==> true + ‘‘ + false ==> ‘truefalse‘
一元运算符优先执行,+[] 转为 number 类型 0,![] 转为 boolean 型 false
new Date(0) - 0 // 0 ==> 0 - 0 ==> 0
‘-‘ 运算符执行 number 类型隐式转换对于 Date 型的值,Date.valueOf() 返回到毫秒的时间戳
new Date(0) + 0
==> ‘Thu Jan 01 1970 02:00:00 GMT+0200 (EET)‘ + 0
==> ‘Thu Jan 01 1970 02:00:00 GMT+0200 (EET)0‘
‘+‘ 运算符触发默认转换,因此使用 toString() 方法,而不是 valueOf()
标签:new 总结 强制类型转换 结果 valueof http nan 类型 ==
原文地址:https://www.cnblogs.com/Leophen/p/11384511.html