利用闭包的强大威力,但从表面上看,它们似乎与回调无关。下面一起来研究其中最强大的一个:模块。

 function foo() {
var something = "cool";
var another = [1, 2, 3];
function doSomething() {
console.log( something );
}
function doAnother() {
console.log( another.join( " ! " ) );
}
}

正如在这段代码中所看到的,这里并没有明显的闭包,只有两个私有数据变量something和another,以及doSomething() 和doAnother() 两个内部函数,它们的词法作用域(而这就是闭包)也就是foo() 的内部作用域。
接下来考虑以下代码:

 function CoolModule() {
var something = "cool";
var another = [1, 2, 3]; function doSomething() {
alert( something );
}
function doAnother() {
alert( another.join( " ! " ) );
}
return {
doSomething: doSomething,
doAnother: doAnother
};
}
var foo = CoolModule();
foo.doSomething(); // cool
foo.doAnother(); // 1 ! 2 ! 3

这个模式在JavaScript 中被称为模块。最常见的实现模块模式的方法通常被称为模块暴露,这里展示的是其变体。我们仔细研究一下这些代码。

首先,CoolModule() 只是一个函数,必须要通过调用它来创建一个模块实例。如果不执行外部函数,内部作用域和闭包都无法被创建。其次,CoolModule() 返回一个用对象字面量语法{ key: value, ... } 来表示的对象。这个返回的对象中含有对内部函数而不是内部数据变量的引用。我们保持内部数据变量是隐藏且私有的状态。可以将这个对象类型的返回值看作本质上是模块的公共API。这个对象类型的返回值最终被赋值给外部的变量foo,然后就可以通过它来访问API 中的属性方法,比如foo.doSomething()。

从模块中返回一个实际的对象并不是必须的,也可以直接返回一个内部函
数。jQuery 就是一个很好的例子。jQuery 和$ 标识符就是jQuery 模块的公
共API,但它们本身都是函数(由于函数也是对象,它们本身也可以拥有属
性)。

doSomething() 和doAnother() 函数具有涵盖模块实例内部作用域的闭包( 通过调用CoolModule() 实现)。当通过返回一个含有属性引用的对象的方式来将函数传递到词法作用域外部时,我们已经创造了可以观察和实践闭包的条件。如果要更简单的描述,模块模式需要具备两个必要条件。

1. 必须有外部的封闭函数,该函数必须至少被调用一次(每次调用都会创建一个新的模块实例)。

2. 封闭函数必须返回至少一个内部函数,这样内部函数才能在私有作用域中形成闭包,并且可以访问或者修改私有的状态。

一个具有函数属性的对象本身并不是真正的模块。从方便观察的角度看,一个从函数调用所返回的,只有数据属性而没有闭包函数的对象并不是真正的模块。上一个示例代码中有一个叫作CoolModule() 的独立的模块创建器,可以被调用任意多次,每次调用都会创建一个新的模块实例。当只需要一个实例时,可以对这个模式进行简单的改进来实现单例模式:

 var foo = (function CoolModule() {
var something = "cool";
var another = [1, 2, 3]; function doSomething() {
alert( something );
}
function doAnother() {
alert( another.join( " ! " ) );
}
return {
doSomething: doSomething,
doAnother: doAnother
};
})();
foo.doSomething(); // cool
foo.doAnother(); // 1 ! 2 ! 3

立即调用这个函数并将返回值直接赋值给单例的模块实例标识符foo。
模块也是普通的函数,因此可以接受参数:

 function CoolModule(id) {
function identify() {
console.log( id );
}
return {
identify: identify
};
}
var foo1 = CoolModule( "foo 1" );
var foo2 = CoolModule( "foo 2" );
foo1.identify(); // "foo 1"
foo2.identify(); // "foo 2"

模块模式另一个简单但强大的变化用法是,命名将要作为公共API 返回的对象:

 var foo = (function CoolModule(id) {
function change() {
// 修改公共API
publicAPI.identify = identify2;
}
function identify1() {
alert( id );
}
function identify2() {
alert( id.toUpperCase() );
}
var publicAPI = {
change: change,
identify: identify1
};
return publicAPI;
})( "foo module" );
foo.identify(); // foo module
foo.change();
foo.identify(); // FOO MODULE

通过在模块实例的内部保留对公共API 对象的内部引用,可以从内部对模块实例进行修改,包括添加或删除方法和属性,以及修改它们的值。

JavaScript利用闭包实现模块化的更多相关文章

  1. JavaScript利用闭包循环绑定事件

    我们经常在做前端面试题的时候,会遇到循环绑定事件后,输出打印结果,很多人总是搞不清楚,今天借此机会跟大家梳理一下闭包相关作用. 1.首先我们举一个简单的例子. html部分: <a href=& ...

  2. JavaScript中闭包实现的私有属性的getter()和setter()方法

    注意: 以下的输出都在浏览器的控制台中 <!DOCTYPE html> <html> <head> <meta charset="utf-8&quo ...

  3. 深入浅出JavaScript之闭包(Closure)

    闭包(closure)是掌握Javascript从人门到深入一个非常重要的门槛,它是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现.下面写下我的学习笔记~ 闭包-无处不 ...

  4. 【转】深入浅出JavaScript之闭包(Closure)

    闭包(closure)是掌握Javascript从人门到深入一个非常重要的门槛,它是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现.下面写下我的学习笔记~ 闭包-无处不 ...

  5. JavaScript作用域闭包简述

    JavaScript作用域闭包简述 作用域 技术一般水平有限,有什么错的地方,望大家指正. 作用域就是变量起作用的范围.作用域包括全局作用域,函数作用域以块级作用域,ES6中的let和const可以形 ...

  6. 【转】理解JavaScript之闭包

    闭包(closure)是掌握Javascript从人门到深入一个非常重要的门槛,它是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现.下面写下我的学习笔记~ 闭包-无处不 ...

  7. javascript,jquery(闭包概念)(转)

    偶尔听人说javascript闭包,让我联想起以前学编译原理和数字逻辑里讲的闭包,以前上课讲的闭包很难懂,而且含有递归的意思在里面,现在不想再查看里面的闭包概念. 但javascript我是经常要用, ...

  8. 理解 Javascript 的闭包

    什么是闭包 闭包是什么?闭包是Closure,这是静态语言所不具有的一个新特性.但是闭包也不是什么复杂到不可理解的东西,简而言之,闭包就是: 闭包就是函数的局部变量集合,只是这些局部变量在函数返回后会 ...

  9. javascript 关于闭包的知识点

    javascript 关于闭包的认识 概念:闭包(closure)是函数对象与变量作用域链在某种形式上的关联,是一种对变量的获取机制. 所以要大致搞清三个东西:函数对象(function object ...

随机推荐

  1. Android SDK Web SDK 接口测试总结

    什么是SDK SDK就是一个程序,提供一些方法,调用这些方法,可以实现一些功能.如:调用银行提供的SDK,可以实现在线支付的功能. 目前主要接手的SDK有js SDK 和android SDK.JS ...

  2. Java 异常归纳总结

    1.异常的分类 1) Checked exception: 这类异常都是Exception的子类 .异常的向上抛出机制进行处理,如果子类可能产生A异常,那么在父类中也必须throws A异常.可能导致 ...

  3. C#中调用Outlook API 发起会议

    原文:C#中调用Outlook API 发起会议 在我上一篇博文中曾提到了 SharePoint 中调用传出电子邮件中的邮件服务器及地址发送邮件 但是,里面的方法只能用于发送普通电子邮件.如果要发起会 ...

  4. QT自动补全设置

    在工具 -> 选项 -> 环境 -> 键盘 中,找到TextEditor -> CompleteThis,修改后面的快捷键就好了 我将它修改为Alt + /

  5. leetcode[55] Merge Intervals

    题目:给定一连串的区间,要求输出不重叠的区间. Given a collection of intervals, merge all overlapping intervals. For exampl ...

  6. SQL Server的链接服务器(MySQL、Oracle、Ms_sql、Access、SYBASE)

    原文:SQL Server的链接服务器(MySQL.Oracle.Ms_sql.Access.SYBASE) 一.使用 Microsoft OLE DB Provider For ODBC 链接MyS ...

  7. 【转】十款让 Web 前端开发人员更轻松的实用工具

    这篇文章介绍十款让 Web 前端开发人员生活更轻松的实用工具.每个 Web 开发人员都有自己的工具箱,这样工作中碰到的每个问题都有一个好的解决方案供选择. 对于每一项工作,开发人员需要特定的辅助工具, ...

  8. 百度Web App在线生成平台Site App体验

    最近收到百度开发者中心邮件,告知之前的百度移动建站服务已经升级为Site App了,Site  App顾名思义是可以创建APP的站点,之前想建立一个APP要么是自己制作,要么是选用国外的在线Web A ...

  9. [置顶] Weblogic节点管理

    配置节点管理之后能方便管理,可以在控制台启动停止被管服务器,一般配置步骤:创建受管服务器,创建machine,屏蔽SSL主机名验证,修改nodemanager.properties,启动nodeman ...

  10. Js中call apply函数以及this用法

    this介绍: C#里this关键字的意义比较确定的.JavaScript的this关键字,随着函数使用场合不同,this的值会发生变化,感觉用法比较混乱,所以,现在是有必要整理一下的时刻了! 总结一 ...