參 照:
http://www.reibang.com/p/554454d951d9
http://blog.csdn.net/xcymorningsun/article/details/52709608
http://imweb.io/topic/582293894067ce9726778be9
https://juejin.im/entry/58aa60182f301e006c32bb97
最初的JS用來實現(xiàn)簡單的頁面邏輯尚粘,因而放在頁面中的 <script> 標簽內(nèi)贤徒,或是通過該標簽來進行調(diào)用蚂且。每一個通過 <script> 標簽調(diào)用的文件此時可被看成單個模塊齐帚,不同模塊的接口都暴露在全局作用域(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(國內(nèi))决左,CommonJS(服務(wù)器端)等規(guī)范愕够,這些(野生)規(guī)范的核心是允許模塊通過 require方法 來同步加載所要依賴的其他模塊,然后通過 exports 或 module.export 來導(dǎo)出需要暴露的接口佛猛。
// 共生
(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要求在頭里引入依賴(依賴前置遂跟,提前執(zhí)行)
CMD可在編寫過程中引入依賴(依賴就近,延遲執(zhí)行)
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發(fā)布后婴渡,module成為標準
標準的使用以import引入模塊
以export導(dǎo)出接口
在Node.js中幻锁,使用CommonJS規(guī)范,
因而使用require引入模塊边臼,
使用module.exports導(dǎo)出接口
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';
部分用法參見 解構(gòu)賦值
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關(guān)鍵字
// 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() // 調(diào)用
「require是賦值過程瘟栖,import是解構(gòu)過程」
至于「該用require還是import葵擎?」這個問題
目前而言,所有的引擎都還沒有實現(xiàn)import
node中是使用了babel將ES6轉(zhuǎn)碼為ES5再執(zhí)行
import語法會被轉(zhuǎn)碼為require半哟。
因而在模塊導(dǎo)出時使用module.exports
在引入時使用import仍然起效
本質(zhì)上酬滤,import會被轉(zhuǎn)碼為require去執(zhí)行。