关于JS类型隐式转换的完整总结
Posted IPyGo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于JS类型隐式转换的完整总结相关的知识,希望对你有一定的参考价值。
不管是在技术聊天群还是论坛里,总能碰到 x + y 等于多少的问题,比如 [] + {} == ?
,如果你不了解其中的原理,那么就插不上话,只能眼睁睁地等大佬解答了。
Type
说到底还是JS类型转换的问题,首先我们先温习一下JS的7种内置类型:
- Number
- String
- Boolean
- Null
- Undefined
- Object
- Symbol
是不是感觉还有Function,毕竟能用typeof获取到?不,函数、数组都是Object的子类型。
类型分为基本类型
和复合类型
两种,除了对象,其它都是基本类型。
To Primitive
发音:[ˈprɪmətɪv]
结构:toPrimitive(input, preferedType = number)
在对象的隐式转换中,对象需要先转成基本类型,并按照如下顺序执行。
- 对象会先调用
valueOf()
。 - 如果没有valueOf这个方法或者valueOf返回的类型不是基本类型,那么对象会继续调用
toString()
方法。 - 如果没有toString这个方法或者toString返回的类型不是基本类型,那么直接抛出
TypeError
异常。
Uncaught TypeError: Cannot convert object to primitive value
接着,我们看下各个对象的转换实现
对象 | valueOf() | toString() |
---|---|---|
Object | 原值 | 字符串 => \\\'[object Object]\\\' |
Function | 原值 | 字符串 => \\\'function xyz() {...}\\\' |
Array | 原值 | 字符串 => \\\'x,y,z\\\' |
Date | 数字时间戳 | 字符串 => \\"Sat May 22 2021...\\" |
Date的默认preferedType=string,即在加法运算中先执行toString()。在 - | * | / | +x | -x 等运算中,先执行valueOf()
数组的toString()可以等效为
join(\\\',\\\')
其中,数组toString()时,遇到null, undefined都被忽略,遇到symbol直接报错,遇到没有toString()的对象也报错。
[1, null, undefined, 2].toString() === \\\'1,,,2\\\';
// Uncaught TypeError: Cannot convert a Symbol value to a string
[1, Symbol(\\\'x\\\')].toString()
// Uncaught TypeError: Cannot convert object to primitive value
[1, Object.create(null)].toString()
To Number
一些特殊值转为数字的例子,等下要用到
Number("0") === 0;
Number("") === 0;
Number(" ") === 0;
Number("\\\\n") === 0;
Number("\\\\t") === 0;
Number(null) === 0;
Number(false) === 0;
Number(true) === 1;
Number(undefined); // NaN
Number("x"); // NaN
加减法 +-
加减法运算中遵循了一些隐式转换规则:
遇到对象先执行ToPrimitive转换为基本类型,然后按照基本类型的规则处理
({}).toString() === "[object Object]"
1 + {} === "1[object Object]"
[2, 3].toString() === "2,3"
1 + [2, 3] === "12,3"
[1] + [2, 3] === "1,2,3"
function test() {}
test.toString() === "function test() {}"
10 + test === "10function test() {}"
加法过程中,遇到字符串,则会被处理为字符串拼接
上面的对象最后也都转成了字符串,遵循本条规则。接着来几个纯字符串的例子
1 + "1" === "11"
1 + 1 === 2
"1" + 1 === "11"
"1" + "1" === "11"
减法操作时,一律需要把类型转换为Number,进行数学运算
3 - 1 === 2
3 - \\\'1\\\' === 2
\\\'3\\\' - 1 === 2
// [].toString() => "" => Number(...) => 0
3 - [] === 3
// {}.toString() => "[object Object]" => Number(...) => NaN
3 - {} // NaN
加法操作时,遇到非字符串的基本类型,都会转Number
1 + true === 2
1 + false === 1
1 + null === 1
1 + undefined // NaN
+ x 和 一元运算 +x 是等效的(以及- x),都会强制转换成Number
+ 0 === 0
- 0 === -0
1 + + "1" === 2
1 + + + + ["1"] === 2
// 负负得正
1 + - + - [1] === 2
// 负负得正
1 - + - + 1 === 2
1 - + - + - 1 === 0
1 + + [""] === 1
// ["1", "2"].toString() => "1,2" => Number(...) => NaN
1 + + ["1", "2"] // NaN
// 吃根香蕉以上是关于关于JS类型隐式转换的完整总结的主要内容,如果未能解决你的问题,请参考以下文章