我的函数不知何故无法访问其父闭包并且缺少变量。如何?

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 的引用,但不是VentFoo

在 JS 运行时闭包有点昂贵。它要求引擎以这样一种方式包装对象,即保留对这些变量的内部引用,以便在执行函数时可以正确解析它们。因此,出于性能原因,Chrome(我怀疑大多数其他引擎也是如此)倾向于优化掉编译脚本时实际未使用的任何闭包变量。这可能会在调试时导致一些令人困惑的事情,但这是意料之中的。

考虑以下示例(注意 xyz 是在外部函数的范围内定义的,而不是在全局范围内):

window.onload = function() 
  var x = 1, y = 2, z = 3;
  (function() 
    debugger;
    x++;
  )();

Alternate JSFiddle demonstration

如果您尝试在此脚本遇到debugger 指令时在控制台上输出xy,您将看到以下内容:

如果您查看 Scope Variable 面板,您会看到:

为什么?因为 Chrome 已经确定 yz 没有在函数中使用,所以编译后的代码不需要保留对变量的引用。如果您在脚本中添加对y 的引用,那么编译器将保留对它的引用,并且在调试器中名称将不再是undefined

【讨论】:

我在 Chrome 31(企业环境)中,这正是正在发生的事情。非常感谢,@p.s.w.g @Louis 对不起,我应该更清楚。如果变量在外部函数的函数范围内,就会发生这种情况。如果它们在全局范围内,那么是的,它们将在内部函数中定义。 @p.s.w.g 是的,使用更新答案中的代码,我可以重现它。 请注意,如果您的脚本包含 eval,chrome 无法优化您的闭包变量 此优化是否记录在某处?【参考方案2】:

如果你使用 评估() 在你的闭包中 Chrome 不会使用它的任何性能优化,这意味着你可以看到 y 的值

【讨论】:

以上是关于我的函数不知何故无法访问其父闭包并且缺少变量。如何?的主要内容,如果未能解决你的问题,请参考以下文章

javascript中的闭包

JavaScript中的闭包

ChatGPT问答[2]-Python类中的方法是闭包吗?是否拥有闭包的性质?

js闭包

闭包与垃圾回收机制

理解闭包