在JavaScript中一个最广泛使用的设计模式是模块的模式。模块模式使用了JavaScript中的一个很棒的特性-闭包- 用来给你方法中的隐私一些控制这样的第三方应用程序不能访问私有数据或覆盖它。在这篇文章中,我会教你什么是闭包,它是如何工作的,以及如何利用它在你的JavaScript代码中实现模块模式。
什么是闭包?
闭包是JavaScript语言的一种构造。在JavaScript内所有变量都能在全局范围内访问,除非变量在函数内用var关键字声明过。variable1 = 1; //全局范围var variable2 = 2; // 不在一个函数内: 全局范围 function funcName() { variable3 = 3; // 没用var关键字声明: 全局范围 var variable4 = 4; //仅本地访问}
var globalvar = 1; //全局范围
function outer() { var outervar = 2; // outer()范围内
function inner() { var innervar = 3; // inner()范围内 console.log(globalvar); // => 1 console.log(outervar); // => 2 console.log(innervar); // => 3 }
console.log(globalvar); // => 1 console.log(outervar); // => 2 console.log(innervar); // => Reference Error引用错误;}
console.log(globalvar); // => 1console.log(outervar); // => Reference Error引用错误console.log(innervar); // => Reference Error引用错误
(function() { // 这函数立即执行,内部所有变量都是私有的}());
用闭包的模块模式
知道了闭包是什么,我们就可以使用模块模式创建对象。通过返回一个对象或变量并赋给一个函数外变量,这样我们可以暴露任何希望暴露给外界的,我们可以有公开和私有的方法。var Module = (function() { // 下面函数是私有的,但可以被公开函数访问 function privateFunc() { … }; // 返回一个对象赋予Module return { publicFunc: function() { privateFunc(); // publicFunc可以直接访问privateFunc } };}());
var Module = (function($, w, undefined) { // … // return {…};}(jQuery, window));
透露模块模式revealing module pattern
透露模块模式是另一种方式来写模块模式,需要更多点代码,但有时更容易理解和阅读。不同于在IIFE中定义所有私有变量并在返回对象中定义公开方法,你把所有方法都写在IIFE中,只是“透露”哪些是你想公开在return语句内的。var Module = (function() { // 现在所有函数直接互访 var privateFunc = function() { publicFunc1(); }; var publicFunc1 = function() { publicFunc2(); }; var publicFunc2 = function() { privateFunc(); }; // 返回对象赋予Module return { publicFunc1: publicFunc1, publicFunc2: publicFunc2 };}());
- 所有函数的声明和实现都在同一个地方,从而制造较少的混乱。
- 私有函数现在可以访问公开函数,如果他们需要。
- 当一个公开函数需要调用另一个公开函数时,他们调用publicFunc2(),而不是用this.publicFunc2(),从而节省了几个字符。
扩展模块模式
我想谈的最后一件事是使用模块模式扩展已经存在的模块。这很常用,当为jQuery之类的库做插件,如下。var jQuery = (function($) { $.pluginFunc = function() { … } return $; }(jQuery));