自己总结了下 js 加法的密之转换规则,如果有错误还请多多指教
其实基本的转换规则只有 3 条
1 如果有对象,则先调用内部函数 ToPrimitive(先调用 valueOf,如果未返回基本数据类型再调用 toString)将其转换为基本数据类型(Undefined Null Boolean Number String)
2 如果有一个是字符串,将另一个转换成字符串(调用内部函数 ToString),返回两个字符串相加的结果
3 如果有一个是数值,将另一个转换成数值(调用内部函数 ToNumber),返回两个数字相加的结果
注 规则 2 的优先级高于规则 3.同时有字符串和数值时,把数值转成字符串
'a' 是字符串,因此将另一个元素转换成字符串(通过 ToString)
'a' + 1 // a1
'a' + true // "atrue"
'a' + null // "anull"
'a' + undefined // "aundefined"
1 是数字,因此将另一个元素转为数字(通过 ToNumber)
1 + true // 2
1 + undefined // NaN
1 + null // 1
[]是对象,则通过 ToPrimitive 转换为字符串后相加
({}).valueOf() // []
// 返回来的是个对象,继续调用 toString
[].toString() // ""
[] + 1// "1"
[] + 'a' // "a"
{}是对象,则通过 ToPrimitive 转换为字符串后相加
({}).valueOf() // {}
// 返回来的是个对象,继续调用 toString
({}).toString() // "[object Object]"
1 + {} // "1[object Object]"
'a' + {} // "a[object Object]"
与对象相加一定返回字符串吗?不一定
var n = new Number(1)
typeof n // "object" n 是个对象,而非数值
n.valueOf() // 1 返回的是 Number,就不再调用 toString 了
n + 1 // 2
// 因此 new Number(1) + 1 返回的是数值而不是字符串
如果修改 n 的 valueOf 方法,让其返回对象,则 n + 1 的结果是字符串而非数值
n.valueOf = function(){return []}
n + 1 // "11"
{} + 1 // 1
{} + 'a' // NaN
{} + '1' // 1
{} + [] // 0
在 firefox 和 ie 中(暂时不管 chrome),浏览器会把{}当作代码块.实际上执行的是一元加操作(在内部调用 ToNumbe),相当于
+1 // 1
+'a' // NaN
+'1' // 1
+[] // 0
给{}外面加个括号,结果就又不一样了.浏览器会正常解析为加法
({}) + 1 // "[object Object]1"
({})+ 'a' //"[object Object]a"
({})+ '1' // "[object Object]1"
({})+ [] // "[object Object]"
或者变成赋值语句也行
var a = {} + 1
console.log(a) // "[object Object]1"
a = ({})+ 'a' //"[object Object]a"
chrome 是最让人摸不着头脑的
如果两个元素都是{}, 则将第一个元素当作对象处理(而非代码块)
{} + {} // "[object Object][object Object]"
{} + {a:1} // "[object Object][object Object]"
如果第二个元素不是{}(数组 字符串等),则将第一个元素当作代码块(实际上执行的是一元加操作)
{} + [] // 0
{} + 1 // 1
{} + 'a' // NaN
{} + '1' // 1
{} + null // 0
不过还是可以通过套括号来解决
({}) + [] // "[object Object]"
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.