You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
否则,令 n, k, 和 s 是整数,使得 k ≥ 1, 10k-1 ≤ s < 10k,s×10****n-k 的数字值是 m,且 k 足够小。如果有数倍于 s 的可能性,选择 s × 10****n-k 最接近于 m 的值作为 s 的值。如果 s 有两个这样可能的值,选择是偶数的那个。要注意的是,k 是 s 在十进制表示中的数字的个数,且 s 不被 10 整除。
注:ECMAScript 的实现者们可能会发现,David M 所写的关于浮点数进行二进制到十进制转换方面的文章和代码很有用:
+ 运算符
JavaScript 让人疑惑的地方之一可能就是隐式转换。
我们可能都见过下面这些代码:
不同于其他语言,这样的结果让人很困惑。
下面就以 + 运算符(包括:一元 + 运算符和加法运算符(+))介绍 JavaScript 的隐式转换。
加法运算符 +
无论隐式转换有怎么样的怪异行为,都需要遵循 ECMAScript 的规定。
加法运算符(+)
加法运算符目的就是执行字符串相接或者数值相加。至于开始举例代码,是加法运算符把对象数组转为字符串或者数字之后相加的结果。
前六点,是转为字符串或数值的过程。需要关注内部方法:ToPrimitive。
ToPrimitive
ToPrimitive 把值转为非对象类型。如果参数是非对象,则不转换,否则根据对象内部方法 [[DefaultValue]] 返回默认值。
[[DefaultValue]]
hint 参数只有 String 和 Number 两种类型。而且只有 Date 对象使用 String。hint 参数如果是 String 就先调用 toString 函数,后调用 valueOf 函数,否则顺序相反。
这里以 hint 参数为 Number 为例:先调用 valueOf ,在调用 toString。
注意最后一段:
[[DefaultValue]] 只能返回原始值。即使宿主对象实现自身的 [[DefaultValue]] 内部方法也要保证返回原始值。
我们不能修改 [[DefaultValue]] 内部方法,但是可以修改 valueOf 或 toString 方法。
这里采用了一元运算符 + ,也会使用到 [[DefaultValue]] 内部方法,这个后面介绍。如果 valueOf 返回的不是原始值
结果是 NaN,因为在 [[DefaultValue]] 内部方法中,会抛出 TypeError 异常。一元运算符 + 对于未定义的值都会返回 NaN。
回到加法运算符规则中。
第七点,如果经过 ToPrimitive 之后,存在至少一个字符串,那么结果就是 ToString(lprim) 和 ToString(rprim) 连接而成的字符串。
第八点,如果都没有字符串,那么返回将加法运算作用于 ToString(lprim) 和 ToString(rprim) 的结果。至于这个结果也是有规定的:
加法作用于数字
总的来说这个结果就是平时我们的数学加法算法,但是考虑了无穷大、无穷小、+0、-0 之类的情况。
ToString 和 ToNumber
在最后两点中出现了 ToString 和 ToNumber。
ToString
需要注意的是数值的情况,需要根据以下规则转换:
这个规则非常复杂,记住前四点就可以了
如果对象转字符串时,需要先 ToPrimitive(obj, String) 转为原始值(在加法运算符时,到达这一步时,已经经过了 ToPrimitive 转换了,不存在对象的情况)。
如果是 symbol 转字符串,会抛类型错误 TypeError (ES6 中规定)。
ToNumber
需要注意的是字符串转数字,直接看这里,也是非常复杂。
对象转数字,也需要先 ToPrimitive(obj, Number) 转为原始值,然后才转为数字。
如果是 symbol 转数字,会抛类型错误 TypeError (ES6 中规定)。
具体分析
首先分析 {} 经过 ToPrimitive 会得到什么值。
因为 {} 是对象,会调用对象的 [[DefaultValue]] 内部方法。{} 不是 Date 类型,所以 hint 是 Number,会先调用对象的 valueOf 方法,返回 {} 自身,不是原始值,继续调用对象 toString 方法,返回 “[object Object]” 字符串。
因为 ToPrimitive({}) 结果是字符串,所以把两个结果连接起来就得到 “[object Object][object Object]”。
[] 也是会调用对象的 [[DefaultValue]] 内部方法。因为数组没有 valueOf 方法,所以调用 toString 方法,返回的值为空 “”。ToPrimitive({}) 的值我们知道是 “[object Object]” ,所以结果就是 “[object Object]” 。
{} + [] 在最新的浏览器中测试结果是 "[object Object]",已经不存在网上说的结果为 0 的情况。
一元运算符 +
一元运算符 + :
一元运算符 + 规则比较简单,直接返回 ToNumber(GetValue(expr)) 结果。ToNumber 在上面已经介绍过了。
参考资料
ECMAScript 英文文档
ECMAScript 维基百科 中文文档
js隐式装箱-ToPrimitive
深入浅出弱类型JS的隐式转换
怪异的JavaScript系列(三)
The text was updated successfully, but these errors were encountered: