- //a.js
- define(function(require, exports, module){
- console.log('a.js执行');
- return {
- hello: function(){
- console.log('hello, a.js');
- }
- }
- });
- //b.js
- define(function(require, exports, module){
- console.log('b.js执行');
- return {
- hello: function(){
- console.log('hello, b.js');
- }
- }
- });
- //main.js
- define(function(require, exports, module){
- console.log('main.js执行');
- var a = require('a');
- a.hello();
- $('#b').click(function(){
- var b = require('b');
- b.hello();
- });
- });
上面的 main.js 执行会输出如下:
定义模块时无需罗列依赖数组,在 factory 函数中需传入形参 require,exports,module,然后它会调用 factory 函数的 toString 方法,对函数的内容进行正则匹配,通过匹配到的 require 语句来分析依赖,这样就真正实现了 commonjs 风格的代码。
main.js 执行 a.js 执行 hello, a.jsa.js 和 b.js 都会预先下载,但是 b.js 中的代码却没有执行,因为还没有点击按钮。当点击按钮的时候,会输出如下:
b.js 执行 hello, b.js如果你一定要挑出一点不爽的话,那就是 b.js 的预先下载了。你可能不太想一开始就下载好所有的资源,希望像 requirejs 那样,等点击按钮的时候再开始下载 b.js。本着兼容并包的思想,seajs 也实现了这一功能,提供 require.async API,在点击按钮的时候,只需这样写:
可以看到 b.js 中的代码此时才执行。这样就真正实现了 "就近书写,延迟执行",不可谓不优雅。
- var b = require.async('b');
- b.hello();
鉴于 seajs 融合了太多的东西,已经无法说它遵循哪个规范了,所以玉伯干脆就自立门户,起名曰 CMD(Common Module Definition)规范,有了纲领,就不会再存在非议了。
你可能会觉得 seajs 无非就是一个抄,把别人家的优点都抄过来组合了一下。其实不然,seajs 是 commonjs 规范在浏览器端的践行者,对于 requirejs 的优点也加以吸收。看人家的名字,就是海纳百川之意。(再论起名的重要性~),既然它的思想是海纳百川,讨论是不是抄就没意义了。
关于模块对外暴漏 API 的方式,seajs 也是融合了各家之长,支持 commonjs 的 exports.xxx = xxx 和 module.exports = xxx 的写法,也支持 AMD 的 return 写法,暴露的 API 可以是任意类型。
b.js 就不会在一开始的时候就加载了。这个 API 可以说是简单漂亮。
定义一个模块不需要专门的工作,因为一个模块的作用就是对外提供 API,所以只需用 exoprt 导出就可以了:
既然模块化开发的呼声这么高,作为官方的 ECMA 必然要有所行动,js 模块很早就列入草案,终于在 2015 年 6 月份发布了 ES6 正式版。然而,可能由于所涉及的技术还未成熟,ES6 移除了关于模块如何加载 / 执行的内容,只保留了定义、引入模块的语法。所以说现在的 ES6 Module 还只是个雏形,半成品都算不上。但是这并不妨碍我们先窥探一下 ES6 模块标准。
- //方式一, a.js
- export
- var a = 1;
- export
- var obj = {
- name: 'abc',
- age: 20
- };
- export
- function run() {....
- }
- //方式二, b.js
- var a = 1;
- var obj = {
- name: 'abc',
- age: 20
- };
- function run() {....
- }
- export {
- a,
- obj,
- run
- }
使用模块的时候用 import 关键字,如:
- import {
- run as go
- }
- from'a'run()
如果想要使用模块中的全部 API,也可以不必把每个都列一遍,使用 module 关键字可以全部引入,用法:
- module foo from 'a'
- console.log(foo.obj);
- a.run();
ES6 Module 的基本用法就是这样,可以看到确实是有些薄弱,而且目前还没有浏览器能支持,只能说它是面向未来了。
在花括号中指明需使用的 API,并且可以用 as 指定别名。
目前我们可以使用一些第三方模块来对 ES6 进行编译,转化为可以使用的 ES5 代码,或者是符合 AMD 规范的模块,例如 ES6 module transpiler。另外有一个项目也提供了加载 ES6 模块的方法,es6-module-loader(https://github.com/ModuleLoader/es6-module-loader
),不过这都是一些临时的方案,或许明年 ES7 一发布,模块的加载有了标准,浏览器给与了实现,这些工具也就没有用武之地了。https://github.com/jrburke/requirejs/wiki/Upgrading-to-RequireJS-2.0#delayed
https://imququ.com/post/amd-simplified-commonjs-wrapping.html
http://www.cnblogs.com/snandy/archive/2012/03/30/2423612.html
http://www.cnblogs.com/snandy/archive/2012/03/12/2390782.html
http://wiki.commonjs.org/wiki/Modules/AsynchronousDefinition
https://github.com/seajs/seajs/issues/588
参考资料:
=======================
未来还是很值得期待的,从语言的标准上支持模块化,js 就可以更加自信的走进大规模企业级开发。
来源: http://www.bubuko.com/infodetail-2087309.html