使用多模块模式时,一个模块内的事件监听器如何调用另一模块的回调函数?
核心错误点
- 错误1:IIFE模块的调用方式错误
你定义的Foo是**立即执行函数表达式(IIFE)**的返回值,执行后直接得到暴露的对象{method1: ...},本身不是函数,所以Foo(???)的写法完全错误,不需要加括号,解构直接写const {method1} = Foo即可。 - 错误2:循环依赖的初始化顺序错误
原代码先初始化Foo,再初始化Foo2,如果Foo的逻辑在初始化阶段就直接访问Foo2的属性,此时Foo2还未创建,自然访问不到。 - 错误3:事件回调的传入方式错误
addEventListener第二个参数需要传入函数引用,Foo2.method2()会立即执行该函数,把返回值(默认是undefined)当做回调,完全不符合要求,正确写法是直接传Foo2.method2。
修正后的单例模块(IIFE模式)实现
只要确保调用模块方法时,两个模块都已完成初始化,就能解决循环依赖问题:
const Foo = (function () { const something = []; const method1 = function(){ // 执行method1时Foo2已经初始化完成,直接访问暴露的method2即可 const bar = document.getElementById("bar"); bar.addEventListener("click", Foo2.method2); }; return {method1}; })(); const Foo2 = (function () { // 直接从Foo对象解构获取暴露的方法,不需要加括号调用 const {method1} = Foo; const somethingElse = 10; const method2 = function(){ console.log("点击事件触发,method2执行"); // 可直接调用从Foo引入的method1 }; return {method2}; })(); // 两个模块都初始化完成后再调用方法绑定事件 window.onload = function() { Foo.method1(); }
工厂函数模式实现(满足作业要求)
如果要求使用工厂函数,可通过参数传递实例的方式解耦依赖,支持多实例共存:
// Foo工厂函数 function createFoo() { const something = []; const method1 = function(foo2Instance){ const bar = document.getElementById("bar"); // 传入Foo2实例,绑定对应实例的method2 bar.addEventListener("click", foo2Instance.method2); }; return {method1}; } // Foo2工厂函数 function createFoo2(fooInstance) { // 初始化时传入Foo实例,直接解构获取方法 const {method1} = fooInstance; const somethingElse = 10; const method2 = function(){ console.log("工厂函数模式下method2执行"); }; return {method2}; } // 实例化流程 const foo = createFoo(); const foo2 = createFoo2(foo); foo.method1(foo2);
模块模式的调用规则
模块模式基于闭包实现,所有需要对外暴露的方法/属性都要写在return的对象里,外部只能访问暴露的内容,私有属性未对外暴露的话完全无法访问,等价于原型链的公开方法逻辑。调用时直接使用模块名.暴露的方法名即可,不需要加prototype。
内容的提问来源于stack exchange,提问作者user16826764
相关产品推荐
相关产品推荐

