参 照:
http://www.jianshu.com/p/554454d951d9
http://blog.csdn.net/xcymorningsun/article/details/52709608
http://imweb.io/topic/582293894067ce9726778be9
https://juejin.im/entry/58aa60182f301e006c32bb97
最初的JS用来实现简单的页面逻辑,因而放在页面中的 <script> 标签内,或是通过该标签来进行调用。每一个通过 <script> 标签调用的文件此时可被看成单个模块,不同模块的接口都暴露在全局作用域(window)下,污染了全局作用域,文件只能按照script标签书写顺序进行加载,且在大型项目中冗杂堆积,可维护性差。
为了在一定程度上避免问题,通常会采用 命名空间 的形式,比如:
var MYNAMESPACE = {
PEOPLE: {
person: function(name) {
this.name = name;
this.getName = function() {
return this.name;
}
}
},
PET: {
dog: function(petName) {
this.petName = petName;
this.getPetName = function() {
return this.petName;
}
}
}
};
var MYNAMESPACE = MYNAMESPACE || {};
后来有了AMD(国外),CMD(国内),CommonJS(服务器端)等规范,这些(野生)规范的核心是允许模块通过 require方法 来同步加载所要依赖的其他模块,然后通过 exports 或 module.export 来导出需要暴露的接口。
// 共生
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD
define(['jquery', 'underscore'], factory);
} else if (typeof exports === 'object') {
// Node, CommonJS之类的
module.exports = factory(require('jquery'), require('underscore'));
} else {
// 浏览器全局变量(root 即 window)
root.returnExports = factory(root.jQuery, root._);
}
}(this, function ($, _) {
// 方法
function a(){}; // 私有方法,因为它没被返回 (见下面)
function b(){}; // 公共方法,因为被返回了
function c(){}; // 公共方法,因为被返回了
// 暴露公共方法
return {
b: b,
c: c
}
}));
AMD要求在头里引入依赖(依赖前置,提前执行)
CMD可在编写过程中引入依赖(依赖就近,延迟执行)
var a = require('a');
// AMD
define(['./a', './b'], function(a, b) { // 依赖必须一开始就写好
a.doSomething()
// 此处略去 100 行
b.doSomething()
});
// CMD
define(function(require, exports, module) {
var a = require('./a')
a.doSomething()
// 此处略去 100 行
var b = require('./b')
// 依赖可以就近书写
b.doSomething()
});
ES6发布后,module成为标准
标准的使用以import引入模块
以export导出接口
在Node.js中,使用CommonJS规范,
因而使用require引入模块,
使用module.exports导出接口
import
ES6中,import需放在文件头部,且前面不允许有其他逻辑代码。
import $ from 'jquery';
import * as _ from '_';
import {a,b,c} from './a';
import {default as alias, a as a_a, b, c} from './a';
部分用法参见 解构赋值
export
如下的语句中,b 在 export 仍可被修改。
export default function() {}
export function a () {}
var b = 'xxx';
export { b }; // {b: b}
setTimeout(() => b = 'ooo', 1000);
export var c = 100;
as关键字
// a.js
var a = function() {};
export {a as fun};
// b.js
import {fun as a} from './a';
a();
// c.js
export function fun() {};
通过「取别名」的方式来解决不同接口重名的问题
在 import 和 export 中皆可使用。
define
在 import 时写这样
import a from './d';
// 等效于,或者说就是下面这种写法的简写,是同一个意思
import {default as a} from './d';
在 export 时写这样
// d.js
export default function() {}
// 等效于:
function a() {};
export {a as default};
*
这个符号用于继承某一个模块全部的接口
比如:
import * as _ from '_';
_.func() // 调用
「require是赋值过程,import是解构过程」
至于「该用require还是import?」这个问题
目前而言,所有的引擎都还没有实现import
node中是使用了babel将ES6转码为ES5再执行
import语法会被转码为require。
因而在模块导出时使用module.exports
在引入时使用import仍然起效
本质上,import会被转码为require去执行。
网友评论