从 JavaScript 中 {}+[] 和 []+{} 谈起

今天一位美女同事问了一个问题,就是解释下图 JavaScript 的运行结果。发在了部门的前端群里,引起了一些讨论,我写下我的一些理解。

各位看官觉得这个运行结果是否诡异?

JavaScript 的隐式转换

1 == '1' // true

在 JavaScript 里,字符串 1 和 数字 1 是相等的,因为相加时都做了 toString 的转化,使用 ‘===’ 来比较结果就不一致了。所以在 {} + [] 相加时,也会产生隐式转化,使其能够相加。

({}.toString()) // [object Object]
[].toString() // ''

Unary plus

符号 ‘+’ 可以用来数字相加、字符串相连,也可以做为一个一元运算符。比较常用的是快速将字符串转化为数字。

+'1' // 1
+undefined // NaN

块级作用域

{} 不仅可以作为对象,也可以用做块级作用域。在 es5 时期,JavaScript 是没有块级作用域,只有函数作用域。es6 配合 let 关键字和 {} 就能实现块级作用域,防止变量污染。

{
let s = 1;
}
console.log(s); // Uncaught ReferenceError: s is not defined

所以当对象字面量相加时,会涉及词法解析为对象或代码块的问题。一般 Chrome 会把 {}; 视为一个代码块,{} 视为对象,如此一来就不难理解上述的异常现象了。

运行这个有意思的例子

var toString = Object.prototype.toString

Object.prototype.valueOf = function () { return 'a'; }
Object.prototype.toString = function () { return 'b'; }
Object.prototype.toLocaleString = function () { return 'a'; }

var s = {a: 1};

console.log(toString.call(s), toString.call('a'))

console.log(s === 'a')
console.log(s == 'a')
console.log(String(s) === 'b')

写完,下班!

参考链接

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Unary_plus_()

我要分享

曾小乱

作者: 曾小乱

喜欢写点有意思的东西

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据