Mastering the Module Pattern (2014) 阅读笔记
模块模式可以帮助开发者更好地组织代码, 在代码中不再过度使用this
和prototype
.
创建模块
使用IIFE创建新的作用域, JS本身不存在”私有”的概念, 用IIFE可以模拟”私有”, 包围所有的业务逻辑, 只返回所需的部分, 避免其他部分暴露在全局作用域.
1 2 3 var Module = (function ( ) { })();
对所创建的模块进行命名, 可以在任何时候调用, 也能将其传到另一个模块.
私有方法 可以在模块内部创建私有方法:
1 2 3 4 5 6 7 var Module = (function ( ) { var privateMethod = function ( ) { }; })();
“return” 如果想在模块内部定义可供外部使用的公有方法, 可以将方法以对象字面量的形式return
, 这样在所创建的模块的命名空间中就存在该方法, 例:
1 2 3 4 5 6 7 8 9 var Module = (function ( ) { return { publicMethod: function ( ) { } }; })();
以这样的形式调用:
返回匿名对象字面量 最简单的模式就是以上所提及的模式, 在模块中返回匿名对象字面量:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 var Module = (function ( ) { var privateMethod = function ( ) {}; return { publicMethodOne: function ( ) { }, publicMethodTwo: function ( ) { }, publicMethodThree: function ( ) { } }; })();
Locally scoped Object Literal 1 2 3 4 5 6 7 8 9 10 11 12 13 var Module = (function ( ) { var myObject = {}; var privateMethod = function ( ) {}; myObject.someMethod = function ( ) { }; return myObject; })();
最后一行返回了myObject
, 我们定义的模块Module
并不在意私有对象字面量是否匿名, 因此对其命名是个好方法, 在最后一行返回, 可以更好地组织代码.
Stacked locally scoped Object Literal 和前一个示例很像, 不过使用了”传统”的对象字面量声明形式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 var Module = (function ( ) { var privateMethod = function ( ) {}; var myObject = { someMethod: function ( ) { }, anotherMethod: function ( ) { } }; return myObject; })();
locally scoped Object Literal 在使用函数之前先定义该函数以避免变量提升(因为function myFunction () {}
会遇到变量提升的问题). 使用var myFunction = function () {}'
语法就不用在意这个问题, 因为我们必须在使用前定义, 同时这个方法也使调试变得更容易, JS解释器会根据我们在代码中定义的顺序渲染各行代码. “stacked”对象字面量的方法还会降低代码可读性, 使其看起来十分冗余. and there is no obvious locally scoped Object namespace for me to bolt public methods onto.
暴露式模块模式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 var Module = (function ( ) { var privateMethod = function ( ) { }; var someMethod = function ( ) { }; var anotherMethod = function ( ) { }; return { someMethod: someMethod, anotherMethod: anotherMethod }; })();
调用”私有”方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 var Module = (function ( ) { var privateMethod = function (message ) { console .log(message); }; var publicMethod = function (text ) { privateMethod(text); }; return { publicMethod: publicMethod }; })(); Module.publicMethod('Hello!' );
不仅限于私有方法, 私有数组和私有对象也可使用这样的方法获取:
1 2 3 4 5 6 7 8 9 10 11 12 13 var Module = (function ( ) { var privateArray = []; var publicMethod = function (somethingOfInterest ) { privateArray.push(somethingOfInterest); }; return { publicMethod: publicMethod }; })();
添加模块 利用实现扩展模块: 下例中ModuleTwo为Module的扩展模块, 添加了extension
方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 var Module = (function ( ) { var privateMethod = function ( ) { }; var someMethod = function ( ) { }; var anotherMethod = function ( ) { }; return { someMethod: someMethod, anotherMethod: anotherMethod, }; })();
1 2 3 4 5 6 7 8 9 10 var ModuleTwo = (function (Module ) { Module.extension = function ( ) { }; return Module; })(Module || {});
私有方法命名惯例 下划线_
以标示私有方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 var Module = (function ( ) { var _privateMethod = function ( ) { }; var publicMethod = function ( ) { _privateMethod(); }; return { publicMethod: publicMethod }; })();