“使用严格”; + jQuery.getScript() = 脚本不能导出到全局命名空间

Posted

技术标签:

【中文标题】“使用严格”; + jQuery.getScript() = 脚本不能导出到全局命名空间【英文标题】:"use strict"; + jQuery.getScript() = script can't export to global namespace 【发布时间】:2012-09-28 09:21:13 【问题描述】:

假设我有以下脚本,称为include_strict.js。执行后我应该定义window.global1

"use strict";

var globalVar = ;
alert(typeof window.globalVar);

但是如果我从一段 javascript 中包含它

$.getScript("include_strict.js");

警报显示undefined。为什么?这是怎么回事?

仅供参考,如果我使用脚本标签包含文件,则不会发生这种情况:

<script type="text/javascript" src="include_strict.js"></script>

在这里,我看到了预期的警报,object。而如果我删除"use strict";,那么jQuery.getScript()&lt;script&gt;; 显示object 的效果是一样的。

我创建了一个示例 (https://docs.google.com/file/d/0B-XXu97sL1Ckb0x0OHptTmVMY00/edit) 来演示这一点。

【问题讨论】:

【参考方案1】:

它使用$.getScript() 使用eval 执行脚本,在严格模式下无法修改全局范围:

其次,eval 的严格模式代码不会将新变量引入周围范围。在普通代码中eval("var x;") 将变量 x 引入到周围函数或全局范围中。这意味着,一般来说,在一个包含对 eval 的调用的函数中,每个不引用参数或局部变量的名称必须在运行时映射到特定的定义(因为 eval 可能引入了一个新变量,该变量将隐藏外部变量)。在严格模式下,eval 只为正在评估的代码创建变量,因此 eval 无法影响名称是指外部变量还是某个局部变量:

来源:https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Functions_and_function_scope/Strict_mode

解决方案不是使用 jQuery 加载脚本,而是将 script 元素附加到 DOM。请注意,您甚至不能使用 jQuery 附加元素;它会自动使用$.getScript()

【讨论】:

你比我多几秒 ;-) 非常有趣。我只是第一次遇到这个问题,这完全有道理。我的问题是我需要在加载后依次执行几个脚本,所以在添加下一个脚本之前我需要知道脚本何时加载。如果我使用将脚本附加到 DOM 的方法,有没有办法让我知道脚本何时加载? .load() 会起作用吗?【参考方案2】:

jQuery evaluates 脚本。 “使用严格;” eval 内部改变了代码的语义。这就是为什么严格模式可能很危险!因为在不支持它的浏览器中,您的代码会执行其他操作。

其次,严格模式代码的 eval 不会将新变量引入周围范围。在普通代码中, eval("var x;") 将变量 x 引入到周围的函数或全局范围中。这意味着,一般来说,在一个包含对 eval 的调用的函数中,每个不引用参数或局部变量的名称必须在运行时映射到特定的定义(因为 eval 可能引入了一个新变量,该变量将隐藏外部变量)。在严格模式下,eval 只为正在评估的代码创建变量,因此 eval 无法影响名称是指外部变量还是某个局部变量。

https://developer.mozilla.org/en/JavaScript/Strict_mode

解决方案是使用window.foo = "bar;" 而不是var foo = "bar";。你应该把你的代码放在一个 IIFE 中,以使“使用严格;”更可预测。

(function(window) 
    "use strict";

    window.globalVar = ;
    alert(typeof window.globalVar);
(window));

【讨论】:

这不是我所需要的,但它让我“点击” - 非常感谢! :)【参考方案3】:

在执行前处理移除严格模式的响应:

 $.ajax(
    url: scriptUrl,
    dataType: "script",
    dataFilter: function (data, type) 
        return data.replace("\'use strict\';", "");
    
);

【讨论】:

以上是关于“使用严格”; + jQuery.getScript() = 脚本不能导出到全局命名空间的主要内容,如果未能解决你的问题,请参考以下文章

“使用严格”是不是已过时?

如何修复“缺少'使用严格'声明”?

JavaScript的严格模式

js备战春招の四の严格模式

始终启用“使用严格”;默认?

Haskell:使用严格性的指南