这会在全球范围内启用“使用严格”吗?
Posted
技术标签:
【中文标题】这会在全球范围内启用“使用严格”吗?【英文标题】:Would this enable "use strict" globally? 【发布时间】:2011-09-22 22:47:05 【问题描述】:与How to enable ECMAScript "use strict" globally?类似但不一样
我已经购买了javascript Patterns,它建议启用 use strict。将它添加到两打 javascript 文件中会有点麻烦,因此在全球范围内启用它会很好。我最初想像这样添加到我的 main.js 的顶部:
"use strict"
require(
priority: ["jquery", "raphael", "myapp"]
);
但是我后来认为它可能只会为该文件启用它。然后我想了想:
<script data-main="lib/main" src="lib/require.js">"use strict"</script>
其中任何一个都可以全局启用 ECMAScript 5 严格模式吗?
【问题讨论】:
第二个例子不会做任何事情。如果脚本标签具有src
属性,则内容将被忽略。这个问题与您链接的问题有何不同?它似乎完美地回答了您的问题(如果有效)。
@Felix:通常情况下,虽然有几个浏览器违反了规则。 :-)
@T.J.: 总是有这些例外......可怕:)
"使用严格";
@Artur:没有它也可以,但是是的,最好包含它。规范非常清楚它是字面意思还是(令人憎恶的)自动分号插入的结果。
【参考方案1】:
TL;DR:
不,一个script
元素中的"use strict"
不会将"use strict"
强加于其他script
元素中的代码。它仅适用于它所属的源文本。
(另外,问题末尾的script
标记:如果script
元素具有src
,则它具有的任何内联文本都被视为“文档”并被忽略。)
更新:
现在在规范中更清楚了(也许在 ES5 中很清楚,但对我来说不是)是的,单独的 script
元素对于 "use strict"
是分开的。原始答案中下面的引用有been changed slightly 说“源文本”而不是“代码单元”,Scripts and Modules 部分更详细。
原答案:
The specification 说:
由于严格模式是在句法代码单元级别选择的,因此严格模式仅施加在此类代码单元内具有局部影响的限制。严格模式不会限制或修改 ECMAScript 语义的任何必须跨多个代码单元一致操作的方面。
(第 4.2.2 节)
那么问题来了:不同的script
标签是否有不同的句法代码单元?
V8(Chrome 中的 JavaScript 引擎)似乎认为它们是独立的,因此将单个 "use strict";
放在页面顶部的全局范围内是行不通的。也许是在我还没有找到的地方指定的,但无论如何,这是一个合理的解释。
假设没有未显示的 foo
声明,则此代码在正常模式下会成为 The Horror of Implicit Globals 的牺牲品:
function test()
try
foo = "bar";
display("foo = " + foo);
catch (e)
display("Exception: " + e);
在正常模式下,它会创建一个新的全局变量foo
,其值为“bar”并显示"foo = bar"
消息。在严格模式下,会抛出异常,因为foo
未定义。
如果我把这个脚本标签放在一个页面中:
<script>
"use strict";
function test()
try
foo = "bar";
display("foo = " + foo);
catch (e)
display("Exception: " + e);
</script>
...我得到了预期的异常 (live example)。但是,如果我将它们放在单独的 script
标签中:
<script>
"use strict";
</script>
<script>
function test()
try
foo = "bar";
display("foo = " + foo);
catch (e)
display("Exception: " + e);
</script>
我没有得到异常(在 V8 上)(example)。如果您考虑浏览器和 JavaScript 引擎的交互方式,这是合理的。
同样,如果该功能在另一个文件中关闭,我会这样做:
<script>
"use strict";
</script>
<script src="/inatoq"></script>
我没有收到异常 (example),大概是出于同样的原因。
请注意此处的示例标记:
<script data-main="lib/main" src="lib/require.js">"use strict"</script>
无效。 script
标签可能任一具有src
属性或内容,但不能两者兼有。 (嗯,基本上;细节here [html5] 和here [HTML 4.01]。)如果它有一个src
元素,浏览器应该忽略内容,大多数人都会这样做。最多。 :-)
【讨论】:
这本书在描述中确实提到了全局,但没有给出如何做到这一点的例子。所以我想我必须在每个模块的开头都有它。我认为因为将它放在 main 中可能会“级联”到 require.js 加载的模块。我想在每个文件中隐式声明它意味着我可以轻松地为违反任何严格规则的模块禁用它。 如果您点击我在上面提供的亚马逊链接,您可以查看这本书,它位于第 5 页。 我认为重要的是要提到句法代码单元通常组合到一个文件中,然后缩小为生产代码。这基本上在全局范围内应用严格模式,因为它现在是一个单一的语法代码单元。需要牢记这一点,这也是像 JSLint 这样的工具在闭包之外不喜欢"use strict";
的原因。【参考方案2】:
JSLint is suddenly reporting: Use the function form of "use strict"
(function ()
"use strict";
// put all of your strict code here
());
【讨论】:
【参考方案3】:不,脚本标签被认为是programs
,因此是code units
。 "use strict"
不应从一个脚本标签转移到另一个。
每个脚本标签都是单独解释的,实际上有自己的范围。这个范围并不明显,因为全局声明的所有内容都将在全局对象上结束,但它仍然存在。字符串"use strict"
将在program
/script 标记的末尾被垃圾回收,因为它没有指针/引用。
【讨论】:
你有以上的参考吗?显然有一种机制在起作用,尽管我不会说 “每个脚本标签......实际上都有自己的范围。” 因为如果他们真的这样做(他们自己的执行上下文)会搞砸var
和函数声明。但显然有些东西,如果你能指出任何事情,我想更好地理解它。谢谢,
什么 T.J.说。这个答案是需要引用的东西。如果如您所说,全局范围都以全局对象结束,那么从一个标记到另一个标记的范围有何不同?我听过的关于 JS 引擎的每一个解释都没有在被称为 LHS 对全局范围的引用的函数中包含任何内容……对于不同脚本标签的不同范围没有区别。可能存在某种不同的范围会影响某些事情,例如严格模式,而不是排除它,但由于该声明与我们看到的许多事情相反,因此需要某种引用。
@JimboJonny:仅供参考,最近的规范对此更加清晰(至少对我而言),我在my answer 的顶部添加了更多最近的链接。我的意思是,我们都知道它是这样工作的,但是......以上是关于这会在全球范围内启用“使用严格”吗?的主要内容,如果未能解决你的问题,请参考以下文章
所有 iPhone 的 PHAsset 图像在全球范围内都是唯一的吗?