作者:原罪
来源:SegmentFault 思否社区
不管是在技术聊天群还是论坛里,总能碰到 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返回的类型不是基本类型,那么对象会继续调用方法。
如果没有toString这个方法或者toString返回的类型不是基本类型,那么直接抛出异常。
接着,我们看下各个对象的转换实现
ate的默认preferedType=string,即在加法运算中先执行toString()。在 - | * | / | +x | -x 等运算中,先执行valueOf()数组的toString()可以等效为
其中,数组toString()时,遇到null, undefined都被忽略,遇到symbol直接报错,遇到没有toString()的对象也报错。
To Number
一些特殊值转为数字的例子,等下要用到
加减法 +-
加减法运算中遵循了一些隐式转换规则:
遇到对象先执行ToPrimitive转换为基本类型,然后按照基本类型的规则处理
加法过程中,遇到字符串,则会被处理为
上面的对象最后也都转成了字符串,遵循本条规则。接着来几个纯字符串的例子
减法操作时,一律需要把类型转换为Number,进行数学运算
加法操作时,遇到非字符串的基本类型,都会转Number
+ x 和 一元运算 +x 是等效的(以及- x),都会强制转换成Number
回到一开始抛出的问题,这样太简单了吧?
对象字面量{}在最前面则不代表对象
不是对象是什么?是你的八块腹肌?别急,看看经典的例子
这啥玩意?说好的"[object Object]"呢?
好吧,这是其实代表的是代码块,最后就变成了,根据前面的原则,数组先被转换成字符串,接着因为+x的运算,字符串被转成数字。
那 { a: 2 } 总该是对象了吧?其实这时候不是代表对象属性,而是被当成了标签(label),标签这东西IE6就已经有了。所以如果我们写成 这样是会报错的,逗号要改成分号才能通过编译。
symbol不能加减
如果在表达式中有symbol类型,那么就会直接报错。比如报错如下:
宽松相等 ==
相等于全等都需要对类型进行判断,当类型不一致时,宽松相等会触发隐式转换。下面介绍规则:
对象与对象类型一致,不做转换
对象与基本类型,对象先执行ToPrimitive转换为基本类型
数字与字符串类型对比时,字符串总是转换成数字
布尔值先转换成数字,再按数字规则操作
null、undefined、symbol
null、undefined与任何非自身的值对比结果都是false,但是 是一个特例。
对比
对比不像相等,可以严格相等(===)防止类型转换,对比一定会存在隐式类型转换。
对象总是先执行ToPrimitive为基本类型
任何一边出现非字符串的值,则一律转换成数字做对比