const MountClickModule = function(){ let num = 0; const handleClick = ()=>{ console.log(++num); } return { countClick:()=>{ document.addEventListener('click',handleClick) } } }(); MountClickModule.countClick(); (function(module) { module.say = ()=>{ console.log(num) //undefined //do something } })(MountClickModule); MountClickModule.say();
这种闭包的坏处:javascript
AMD 和 CommonJS 是两个互相竞争的标准,都可定义 JavaScript 模块。除了语法和原理的区别以外,主要区别是 AMD 的设计理念是明确基于浏览器,而 CommonJS 的设计是面向通用 JavaScript 环境
AMD 异步模块定义规范制定了定义模块的规则,这样模块和模块的依赖能够被异步加载。这和浏览器的异步加载模块的环境恰好适应(浏览器同步加载模块会致使性能、可用性、调试和跨域访问等问题)。html
目前,AMD 最流行的实现是 RequireJS
。java
define("alpha", ["require", "exports", "beta"], function (require, exports, beta) { exports.verb = function() { return beta.verb(); //Or: return require("beta").verb(); } });
AMD 提供名为 aplha 的函数,它接收一下参数:git
id
,是个字符串。它指的是定义中模块的名字,这个参数是可选的。若是没有提供该参数,模块的名字应该默认为模块加载器请求的指定脚本的名字。能够看出,AMD 有一下几项有点:es6
CMD 是 SeaJS 在推广过程当中对模块定义的规范化产出,在 CMD 规范中,一个模块就是一个文件。代码的书写格式以下:github
define(function (require, exports, module) { const foo = require('./foo') a.doSomething() // ... const bar = require('./bar') // 依赖能够就近书写 b.doSomething() // do something else })
AMD 的设计明确基于浏览器,而 CommonJS 的设计是面向通用 JavaScript 环境。CommonJS 目前在 Nodejs 社区中具备最多的用户。CommonJS 使用基于文件的模块,因此每一个文件中都只能定义一个模块,CommonJs 提供变量 module,该变量具备属性 exports,经过 exports 很容易扩展属性。最后,module.exports 做为模块的公共接口。typescript
const beta = require('beta'); function alpha(){ return beta.verb(); //Or: return require("beta").verb(); } module.exports = alpha;
CommonJS 要求一个文件就是一个模块,文件中的代码就是模块的一部分,因此不须要使用当即执行函数来包装变量,在模块中定义的变量都是安全的再模块中,不会泄露到全局做用域。只有经过 module.exports
对象暴露的对象或函数才能够在函数外部访问
CommonJS 具备如下特色:api
这是 CommonJS 在服务端更流行的缘由。跨域
ES6 模块结合了CommonJS 和 AMD 的有点,具体以下:数组
既 ES6 结合了两种模块化的有点,基于文件系统,既支持异步也支持同步,由于浏览器并无实现 ES6 的模块化 API 因此具体是异步仍是同步取决于loader api
ES6 模块的主要思想是必须显示的使用标志符导出模块,才能从外部访问模块。其余标志符,甚至在最顶级做用域中定义的标识符,只能在模块中使用。
ES6 引入两个关键字:
从index.js模块中导出:
const hello = 'hello'; export const name = 'yunfly' export function sayHi(){ return `${hello} ${name}!` }
也能够在模块最后一块儿导出:
// foo.js const hello = 'hello'; export const name = 'yunfly' export function sayHi(){ return `${hello} ${name}!` } export { name, sayHi } // export { name as firstName, sayHi } // bar.js // 使用 as 设置导如别名 import { name as firstName, sayHi } from 'foo' console.log(name) sayHi() //bar2.js // 导出所有标识符: import * as sayModule from 'foo'; console.log(sayModule.name) sayModule.sayHi()
// foo.js class Foo {} export default Foo // bar.js import Foo from './foo';
这存在一些可维护性的问题:
文章参考:《JavaScript忍者秘籍》