在我的顶级功能中,我使用require.js导入一些依赖项.他们在那里,没问题.在这个函数中,我定义一个回调函数,并尝试使用通过require.js导入的一些变量,即父闭包中的变量.
而且他们只是不在那里,正如断点和Chrome浏览器的范围变量面板上的一样.
我明白,fn.apply和朋友只是设置上下文到这一点,而不是他们可以破坏对闭包的引用或改变范围链.
define([ 'backbone','backbone.vent','app/utils/foo','app/services/intent' ],function(Backbone,Vent,Foo) { 'use strict'; // Backbone,and Foo are defined here Vent.on('myevent',function(options) { // Backbone is defined here,but not Vent or Foo. }); });
这怎么可能?
我该怎么解决?
解决方法
我怀疑你设置断点的函数包含对Backbone的引用,而不是Vent或Foo.
在JS运行时关闭有点贵.它需要引擎将对象包起来,使其保持对这些变量的内部引用,以便在执行函数时正确地解析它们.因此,出于性能原因,Chrome(并且我怀疑大多数其他引擎)也倾向于优化在脚本编译时实际不使用的任何闭包变量.这可能会在调试时导致一些混乱的事情,但这是可以预料的.
考虑以下示例(注释x,y和z在外部函数的范围中定义,而不在全局范围内):
window.onload = function() { var x = 1,y = 2,z = 3; (function() { debugger; x++; })(); }
Alternate JSFiddle demonstration
如果您尝试在控制台上输出x和y,当此脚本命中调试器指令时,您将看到:
如果您看到“范围变量”面板,您将看到:
为什么?因为Chrome已经确定y和z在函数内没有使用,所以编译代码不需要保留对变量的引用.如果在脚本中添加对y的引用,那么编译器将保留对它的引用,并且该名称将不再在调试器中定义.