调试揭示模块模式:功能不在范围内直到被调用?
如果我在Chrome开发人员工具中运行此代码:
var test = (function () {
var publicFunction,
privateFunction1,
privateFunction2;
privateFunction1 = function privateFunction1() {
return true;
};
privateFunction2 = function privateFunction2() {
return true;
};
publicFunction = function publicFunction() {
privateFunction1();
debugger;
};
return {
publicFunction: publicFunction
};
})();
为什么privateFunction1
在断点范围内,而privateFunction2
不在?
迷人的问题。
privateFunction2
所在范围内publicFunction
,但publicFunction
从来没有真正使用它。 我相信你在调试器中看到的是因为V8(Chrome的JavaScript引擎)出于各种原因(包括最小化内存使用)优化闭包的内容。
理论上,根据规范, publicFunction
关闭(有一个持久的引用)所有定义范围内的符号。 具体而言,创建了一个执行上下文,用于调用最外层的匿名函数,并且该执行上下文具有包含关联绑定对象的词汇环境, publicFunction
具有隐式匿名引用。 该绑定对象具有(在理论上)名称publicFunction
, privateFunction1
, privateFunction2
和其他一些东西( arguments
等)的属性。
但问题是, publicFunction
实际上并没有引用除privateFunction1
任何privateFunction1
,并且代码已经存在,它不能引用任何其他内容。 为了引用其他任何东西,你必须改变它的代码,当然他们会做出不同的决定。 publicFunction
的代码没有eval(string)
或new Function(string)
调用,所以V8可以自由地对它所引用的符号进行静态分析。 这意味着,如果缺少调试器,则绑定对象保留其他属性没有任何意义。 他们从未使用过。
由于V8是一个积极优化的编译器(是,编译器),显然它从执行上下文的绑定对象中删除了死的属性。
如果我在publicFunction
中添加一些使用privateFunction2
的东西,我可以在控制台中引用它,就像我可以使用privateFunction1
。
上一篇: Debugging Revealing Module Pattern: functions not in scope until called?