我的函数以某种方式无法访问其父闭包并且缺少变量.怎么样?

Ala*_* H. 13 javascript closures scope scope-chain requirejs

在我的顶级函数中,我使用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.
    });
});
Run Code Online (Sandbox Code Playgroud)

这怎么可能呢?

我该如何解决?

p.s*_*w.g 29

我怀疑你设置断点的函数包含一个引用Backbone,但不包含VentFoo.

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

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

window.onload = function() {
  var x = 1, y = 2, z = 3;
  (function() {
    debugger;
    x++;
  })();
}
Run Code Online (Sandbox Code Playgroud)

替代JSFiddle演示

如果您尝试在此脚本命中时输出xy在控制台上debugger,您将看到:

控制台输出

如果你看一下Scope Variable面板,你会看到:

范围变量

为什么?因为Chrome已经确定y并且z未在函数中使用,因此编译代码不需要保留对变量的引用.如果y在脚本中添加引用,则编译器将保留对它的引用,并且该名称将不再undefined位于调试器中.