遵循規範node
–require 是 AMD規範引入方式jquery
–import是es6的一個語法標準,若是要兼容瀏覽器的話必須轉化成es5的語法es6
調用時間編程
–require是運行時調用,因此require理論上能夠運用在代碼的任何地方數組
–import是編譯時調用,因此必須放在文件開頭瀏覽器
本質babel
–require是賦值過程,其實require的結果就是對象、數字、字符串、函數等,再把require的結果賦值給某個變量閉包
–import是解構過程,可是目前全部的引擎都尚未實現import,咱們在node中使用babel支持ES6,也僅僅是將ES6轉碼爲ES5再執行,import語法會被轉碼爲require編程語言
require時代的模塊模塊化
node編程中最重要的思想之一就是模塊,而正是這個思想,讓JavaScript的大規模工程成爲可能。模塊化編程在js界流行,也是基於此,隨後在瀏覽器端,requirejs和seajs之類的工具包也出現了,能夠說在對應規範下,require統治了ES6以前的全部模塊化編程,即便如今,在ES6 module被徹底實現以前,仍是這樣。
node的module遵循CommonJS規範,requirejs遵循AMD,seajs遵循CMD,雖各有不一樣,但總之仍是但願保持較爲統一的代碼風格。
// a.js
// -------- node -----------
module.exports = {
a : function() {},
b : 'xxx'
};
// ----------- AMD or CMD ----------------
define(function(require, exports, module){
module.exports = {
a : function() {},
b : 'xxx'
};
});
能夠看出,爲了保持風格的高度統一,除了在瀏覽器端的模塊中要使用一個define函數來提供模塊的閉包之外,其餘代碼能夠徹底一致。
// b.js
// ------------ node ---------
var m = require('./a');
m.a();
// ------------ AMD or CMD -------------
define(function(require, exports, module){
var m = require('./a');
m.a();
});
在使用上,也很是類似。雖然AMD or CMD提供了更加豐富的風格,可是咱們本文主要是討論node環境下,因此不作擴展。
ES6中的module
ES6發佈的module並無直接採用CommonJS,甚至連require都沒有采用,也就是說require仍然只是node的一個私有的全局方法,module.exports也只是node私有的一個全局變量屬性,跟標準半毛錢關係都沒有。
export導出模塊接口
export的用法挺複雜的,具體有哪些能夠看 這裏 。這裏舉幾個例子:
// a.js
export default function() {}
export function a () {}
var b = 'xxx';
export {b}; // 這是ES6的寫法,實際上就是{b:b}
setTimeout(() => b = 'ooo', 1000);
export var c = 100;
在要導出的接口前面,加入export指令。
在export以後,b還能夠被修改,這和CommonJS有着巨大不一樣,關於內部機理的東西,本文就無恥的省略了。
注意,下面的語法有嚴重錯誤:
// 錯誤演示
export 1; // 絕對不能夠
var a = 100;
export a;
export在導出接口的時候,必須與模塊內部的變量具備一一對應的關係。直接導出1沒有任何意義,也不可能在import的時候有一個變量與之對應。 export a 雖然看上去成立,可是 a 的值是一個數字,根本沒法完成解構,所以必須寫成 export {a} 的形式。即便a被賦值爲一個function,也是不容許的。並且,大部分風格都建議,模塊中最好在末尾用一個export導出全部的接口,例如:
export {fun as default,a,b,c};
import導入模塊
import的語法跟require不一樣,並且import必須放在文件的最開始,且前面不容許有其餘邏輯代碼,這和其餘全部編程語言風格一致。
import的使用和export同樣,也挺複雜,能夠在 這裏 大體瞭解。舉幾個例子:
import $ from 'jquery';
import * as _ from '_';
import {a,b,c} from './a';
import {default as alias, a as a_a, b, c} from './a';
這裏有一些坑,暫時不透露,下面會講到。
import後面跟上花括號的形式是最基本的用法,花括號裏面的變量與export後面的變量一一對應。這裏,你必須瞭解 對象的解構賦值 的知識,沒這知識,你根本無法在這裏裝逼。瞭解瞭解構賦值,這裏的「一一對應」的關係就能具體理解了。
as關鍵字
編程的同窗對as都容易理解,簡單的說就是取一個別名。export中能夠用,import中其實能夠用:
// a.js
var a = function() {};
export {a as fun};
// b.js
import {fun as a} from './a';
a();
上面這段代碼,export的時候,對外提供的接口是fun,它是a.js內部a這個函數的別名,可是在模塊外面,認不到a,只能認到fun。
import中的as就很簡單,就是你在使用模塊裏面的方法的時候,給這個方法取一個別名,好在當前的文件裏面使用。之因此是這樣,是由於有的時候不一樣的兩個模塊可能經過相同的接口,好比有一個c.js也經過了fun這個接口:
// c.js
export function fun() {};
若是在b.js中同時使用a和c這兩個模塊,就必須想辦法解決接口重名的問題,as就解決了。
default關鍵字
其餘人寫教程什麼的,都把default放到export那個部分,我以爲不利於理解。在export的時候,可能會用到default,說白了,它實際上是別名的語法糖:
// d.js
export default function() {}
// 等效於:
function a() {};
export {a as default};
在import的時候,能夠這樣用:
import a from './d';
// 等效於,或者說就是下面這種寫法的簡寫,是同一個意思
import {default as a} from './d';
這個語法糖的好處就是import的時候,能夠省去花括號{}。簡單的說,若是import的時候,你發現某個變量沒有花括號括起來(沒有*號),那麼你在腦海中應該把它還原成有花括號的as語法。
因此,下面這種寫法你也應該理解了吧:
import $,{each,map} from 'jquery';
import後面第一個 $ 是 {defalut as $} 的替代寫法。
*符號
*就是表明全部,只用在import中,咱們看下兩個例子:
import * as _ from '_';
在乎義上和 import _ from '_'; 是不一樣的,雖然實際上後面的使用方法是同樣的。它表示的是把 '_' 模塊中的全部接口掛載到 _ 這個對象上,因此能夠用 _.each 調用某個接口。
另外還能夠經過*號直接繼承某一個模塊的接口:
export * from '_';
// 等效於:
import * as all from '_';
export all;
*符號儘量少用,它其實是使用全部export的接口,可是頗有可能你的當前模塊並不會用到全部接口,可能僅僅是一個,因此最好的建議是使用花括號,用一個加一個。
該用require仍是import?
require的使用很是簡單,它至關於module.exports的傳送門,module.exports後面的內容是什麼,require的結果就是什麼,對象、數字、字符串、函數……再把require的結果賦值給某個變量,至關於把require和module.exports進行平行空間的位置重疊。
並且require理論上能夠運用在代碼的任何地方,甚至不須要賦值給某個變量以後再使用,好比:
require('./a')(); // a模塊是一個函數,當即執行a模塊函數
var data = require('./a').data; // a模塊導出的是一個對象
var a = require('./a')[0]; // a模塊導出的是一個數組
你在使用時,徹底能夠忽略模塊化這個概念來使用require,僅僅把它當作一個node內置的全局函數,它的參數甚至能夠是表達式:
require(process.cwd() + '/a');
可是import則不一樣,它是編譯時的(require是運行時的),它必須放在文件開頭,並且使用格式也是肯定的,無可置疑。它不會將整個模塊運行後賦值給某個變量,而是隻選擇import的接口進行編譯,這樣在性能上比require好不少。
從理解上,require是賦值過程,import是解構過程,固然,require也能夠將結果解構賦值給一組變量,可是import在遇到default時,和require則徹底不一樣: var $ = require('jquery'); 和 import $ from 'jquery' 是徹底不一樣的兩種概念。
上面徹底沒有回答「改用require仍是import?」這個問題,由於這個問題就目前而言,根本無法回答,由於目前全部的引擎都尚未實現import,咱們在node中使用babel支持ES6,也僅僅是將ES6轉碼爲ES5再執行,import語法會被轉碼爲require。這也是爲何在模塊導出時使用module.exports,在引入模塊時使用import仍然起效,由於本質上,import會被轉碼爲require去執行。
可是,咱們要知道這樣一個道理,ES7很快也會發布,js引擎們會盡快實現ES6標準的規定,若是一個引擎連標準都實現不了,就會被淘汰, ES6是早晚的事 。若是你如今仍然在代碼中部署require,那麼等到ES6被引擎支持時,你必須升級你的代碼,而若是如今開始部署import,那麼將來可能只須要作不多的改動。