为什么严格模式会使如此简单的操作如此不同?

Why does strict mode make such simple actions such different?

有一个极其简单的算法,根据 "use strict".

的存在,它在两种情况下的工作方式出奇地不同

案例 1:

如果func()声明在严格模式下,那么控制台记录原始

"use strict";

// strict mode is on
Object.prototype.func = function() { return this; } // do nothing with the object

console.log( (4).func() ); // 4; primitive

案例二:

如果func()声明在严格模式之外,那么控制台记录相同值的对象

// strict mode is off
Object.prototype.func = function() { return this; } // do nothing with the object

"use strict";

console.log( (4).func() ); // Number {[[PrimitiveValue]]: 4}; object

这种差异的根源是什么?这种转换的原因是什么?
如此简单的动作,在严格模式的各种状态下,怎么会有如此不同?

this不被装箱是严格模式的有意改动之一。这可以防止 JavaScript 代码访问原语,从而简化它以证明 JavaScript 片段是无害的。我猜它也有轻微的速度改进。

详情请参考MDN

在此特定示例中,任何不是对象、函数或数组的东西都是原语。 (函数和数组在技术上是对象。)原始值的问题是你不能有方法。所以,你不能做类似 "hello world".toUpperCase() 的事情。一般来说,程序员喜欢拥有与他们正在使用的任何类型的对象相关的方法,而不是大量全局可用的函数(例如 parseInt)。

因此,JavaScript 有 StringNumber 和其他具有 toUpperCasetoLowerCasetoString 方法的对象。当我们在字符串或数字上调用这些方法之一时,JavaScript 包装在相应的对象中,调用该方法并 returns 原始结果。这一切都在幕后发生,我们通常不必担心。

除非它不起作用——就像在你的例子中一样。 JavaScript 的早期版本中出现了一些错误,但由于向后兼容,我们无法真正更改这些内容。如果我在 1995 年创建了一个使用 JavaScript 的网站,然后在 1997 年更改了规则,我的网站就会突然崩溃。

也就是说,很多错误都有合理的解决方案,如果我们可以选择一些额外的安全措施,那就太好了。较旧的浏览器看到孤独的字符串 "use strict" 并忽略它。较新的浏览器会看到这一点并选择加入一组新规则,概述 here