为啥严格模式会使如此简单的动作如此不同?
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
)。
所以,javascript 有 String
、Number
和其他具有 toUpperCase
、toLowerCase
和 toString
等方法的对象。当我们在字符串或数字上调用这些方法之一时,JavaScript 会包装相应的对象,调用该方法并返回原始结果。这一切都发生在幕后,我们通常不必担心。
除非它不起作用——就像在你的例子中一样。 JavaScript 的早期版本中存在一些错误,但由于向后兼容性,我们无法真正更改这些内容。如果我在 1995 年创建了一个使用 JavaScript 的网站,然后在 1997 年改变了规则,我的网站就会突然崩溃。
也就是说,很多此类错误都有合理的解决方案,如果我们可以选择采取一些额外的安全措施,那就太好了。较旧的浏览器看到孤独的字符串“use strict”并忽略它。较新的浏览器会看到这一点并选择加入一组新规则,概述为here。
【讨论】:
很好的答案,谢谢!虽然,我不明白,为什么要做出这样的改变(不要在返回时“拆箱”传递的对象),——除了更好的优化可能......【参考方案2】:this
不被装箱是严格模式的有意更改之一。这可以防止 JavaScript 代码访问原语,从而简化它以证明 JavaScript sn-p 是无害的。我猜它还会带来轻微的速度提升。
更多详情,请参考MDN。
【讨论】:
以上是关于为啥严格模式会使如此简单的动作如此不同?的主要内容,如果未能解决你的问题,请参考以下文章
为啥我的 JavaScript 在 Safari 的严格模式下无法正常工作?