为啥严格模式会使如此简单的动作如此不同?

Posted

技术标签:

【中文标题】为啥严格模式会使如此简单的动作如此不同?【英文标题】:Why does strict mode make such simple actions such different?为什么严格模式会使如此简单的动作如此不同? 【发布时间】:2016-08-26 12:37:29 【问题描述】:

有一个非常简单的算法,它在两种情况下的工作方式出人意料地不同,这取决于"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

案例 2

如果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传递给严格模式下的函数的值不会被强制成为一个对象(又名“盒装”)” 【参考方案1】:

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

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

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

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

【讨论】:

很好的答案,谢谢!虽然,我不明白,为什么要做出这样的改变(不要在返回时“拆箱”传递的对象),——除了更好的优化可能......【参考方案2】:

this 不被装箱是严格模式的有意更改之一。这可以防止 JavaScript 代码访问原语,从而简化它以证明 JavaScript sn-p 是无害的。我猜它还会带来轻微的速度提升。

更多详情,请参考MDN。

【讨论】:

以上是关于为啥严格模式会使如此简单的动作如此不同?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的 JavaScript 在 Safari 的严格模式下无法正常工作?

为啥 Facebook 身份验证 SDK 在不同模式下的表现如此不同?

为啥我的函数在严格模式(函数形式)下未定义?

为啥这个 Haskell 程序表现如此糟糕?

为啥整数上的 in_array 严格模式比非严格模式慢?

在不破坏严格别名的情况下有效地生成字节缓冲区