JavaScript中跨词法作用域访问函数的实现方案——如何让f2()访问内部函数f1()?
如何让函数f2()访问内部函数f1()?
先看你的代码结构哈——首先得明确一个点:f2本身其实已经能直接访问f1了,毕竟俩函数都定义在同一个factory函数的词法作用域里,天生就是“邻居”,直接调用就行:
(function(global, factory) { global.m = {}; factory(global.m); })(this, (function(exports) { function f1() { return "f1"; }; function f2(f) { // f2里直接调用f1,完全没问题 console.log(f1()); // 会输出"f1" return f.call(null, "f2"); }; exports.f2 = f2; }))
不过我猜你真正的需求是:让传给f2的那个外部回调函数能访问到f1?毕竟你写的m.f2(function(a) { return a + f1() })里,这个回调是在全局作用域定义的,它的词法作用域根本碰不到factory内部的f1,运行起来肯定会报f1 is not defined的错。如果是这个需求,给你几个可行的方案:
方案1:把f1作为额外参数传给回调
修改f2的逻辑,在调用传入的回调时,把f1当成参数递过去:
(function(global, factory) { global.m = {}; factory(global.m); })(this, (function(exports) { function f1() { return "f1"; }; function f2(f) { // 调用回调时多传一个f1参数 return f.call(null, "f2", f1); }; exports.f2 = f2; })) // 回调里接收这个参数,然后调用 m.f2(function(a, f1) { return a + f1() }) // 结果是"f2f1"
方案2:通过this上下文传递f1
调用回调的时候改变它的this指向,把f1挂到this对象上:
(function(global, factory) { global.m = {}; factory(global.m); })(this, (function(exports) { function f1() { return "f1"; }; function f2(f) { // 把包含f1的对象作为this传给回调 return f.call({ f1: f1 }, "f2"); }; exports.f2 = f2; })) // 回调里通过this.f1调用 m.f2(function(a) { return a + this.f1() }) // 结果是"f2f1"
方案3:把f1暴露到全局(不推荐)
如果不在乎f1的私有性,直接把它也挂载到exports(也就是m对象)上就行,但这样f1就不再是内部私有函数了:
(function(global, factory) { global.m = {}; factory(global.m); })(this, (function(exports) { function f1() { return "f1"; }; function f2(f) { return f.call(null, "f2"); }; exports.f2 = f2; exports.f1 = f1; // 把f1暴露出去 })) // 回调里通过m.f1调用 m.f2(function(a) { return a + m.f1() }) // 结果是"f2f1"
方案4:在闭包作用域内定义回调
如果你的场景允许把回调放在factory内部,那它自然就能访问f1——不过这样回调就没法在全局调用了:
(function(global, factory) { global.m = {}; factory(global.m); })(this, (function(exports) { function f1() { return "f1"; }; function f2(f) { return f.call(null, "f2"); }; exports.f2 = f2; // 在factory内部定义回调,直接就能用f1 exports.f2(function(a) { return a + f1() }); }))
总结一下:要是只是f2自己要访问f1,那啥都不用做,天生就能访问;要是外部传给f2的回调要访问f1,优先选方案1或2,这俩不会破坏f1的私有性,比较优雅。
内容的提问来源于stack exchange,提问作者Dmitry Perfilyev
相关产品推荐
相关产品推荐

