require和import的區別

遵循規範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,那麼將來可能只須要作不多的改動。

相關文章
相關標籤/搜索