我的函数不知何故无法访问其父闭包并且缺少变量。如何?
Posted
技术标签:
【中文标题】我的函数不知何故无法访问其父闭包并且缺少变量。如何?【英文标题】:My function somehow doesn’t have access to its parent closure & is missing variables. How? 【发布时间】:2014-03-21 22:54:50 【问题描述】:在我的***函数中,我使用 require.js 导入了一些依赖项。他们在那里,没问题。在这个函数中,我定义了一个回调函数,并尝试使用一些通过 require.js 导入的变量,也就是父闭包中的变量。
它们根本不存在,正如断点和浏览 Chrome 检查器的 Scope Variables 面板所证实的那样。
我知道fn.apply
和朋友只设置了this
的上下文,而不是他们可以破坏对闭包的引用或更改作用域链。
define([
'backbone',
'backbone.vent',
'app/utils/foo',
'app/services/intent'
], function(Backbone, Vent, Foo)
'use strict';
// Backbone, Vent, and Foo are defined here
Vent.on('myevent', function(options)
// Backbone is defined here, but not Vent or Foo.
);
);
这怎么可能?
我该如何解决?
【问题讨论】:
相关代码可能有助于诊断问题。 garbage collection with node.js 的可能副本。另见here 和there 【参考方案1】:我怀疑您设置断点的函数包含对Backbone
的引用,但不是Vent
或Foo
。
在 JS 运行时闭包有点昂贵。它要求引擎以这样一种方式包装对象,即保留对这些变量的内部引用,以便在执行函数时可以正确解析它们。因此,出于性能原因,Chrome(我怀疑大多数其他引擎也是如此)倾向于优化掉编译脚本时实际未使用的任何闭包变量。这可能会在调试时导致一些令人困惑的事情,但这是意料之中的。
考虑以下示例(注意 x
、y
和 z
是在外部函数的范围内定义的,而不是在全局范围内):
window.onload = function()
var x = 1, y = 2, z = 3;
(function()
debugger;
x++;
)();
Alternate JSFiddle demonstration
如果您尝试在此脚本遇到debugger
指令时在控制台上输出x
和y
,您将看到以下内容:
如果您查看 Scope Variable 面板,您会看到:
为什么?因为 Chrome 已经确定 y
和 z
没有在函数中使用,所以编译后的代码不需要保留对变量的引用。如果您在脚本中添加对y
的引用,那么编译器将保留对它的引用,并且在调试器中名称将不再是undefined
。
【讨论】:
我在 Chrome 31(企业环境)中,这正是正在发生的事情。非常感谢,@p.s.w.g @Louis 对不起,我应该更清楚。如果变量在外部函数的函数范围内,就会发生这种情况。如果它们在全局范围内,那么是的,它们将在内部函数中定义。 @p.s.w.g 是的,使用更新答案中的代码,我可以重现它。 请注意,如果您的脚本包含 eval,chrome 无法优化您的闭包变量 此优化是否记录在某处?【参考方案2】:如果你使用 评估() 在你的闭包中 Chrome 不会使用它的任何性能优化,这意味着你可以看到 y 的值
【讨论】:
以上是关于我的函数不知何故无法访问其父闭包并且缺少变量。如何?的主要内容,如果未能解决你的问题,请参考以下文章