import和require的區別

關於 importrequire 的不一樣,其實能夠理解成 CommonJs 和 ES Module 的區別。這二者都是前端模塊化的規範。前端

咱們在 node 裏使用的是 CommonJs,在前端頁面的時候,用的是 ES Module,這二者的區別,仍是很容易混淆的,因此整理一下 CommonJs 和 ES Moudule 的相關知識點,把這裏好好的整理一下。node

1、CommonJses6

1.1 概述json

Nodejs 是 CommonJS 規範的主要實踐者,在 CommonJs 裏每一個文件就是一個模塊,有本身的做用域。在一個文件裏面定義的變量、函數、類,都是私有的,對其餘文件不可見。CommonJs 提供了四個重要的環境變量爲模塊化的實現提供支持:moduleexportsrequireglobal。CommonJS 規定,每一個模塊內部,module 變量表明當前模塊。這個變量是一個對象,它的 exports 屬性(即 module.exports )是對外的接口。加載某個模塊,實際上是加載該模塊的 module.exports 屬性。數組

var x = 5;
var addX = function (value) {
 return value + x;
};

module.exports.x = x;
module.exports.addX = addX;

而使用 require 方法來引入並加載模塊緩存

var example = require('./example.js');

console.log(example.x); // 5
console.log(example.addX(1)); // 6

1.2 CommonJS模塊的特色模塊化

  • 全部代碼都運行在模塊做用域,不會污染全局做用域。
  • CommonJS 用同步的方式加載模塊。
  • 模塊能夠屢次加載,可是隻會在第一次加載時運行一次,而後運行結果就被緩存了,之後再加載,就直接讀取緩存結果。要想讓模塊再次運行,必須清除緩存。
  • 模塊加載的順序,按照其在代碼中出現的順序。

關於變量:函數

一、module 對象是 node 裏的 Module 構造函數的實例,表明當前模塊。具備如下屬性:ui

  • module.id 模塊的識別符,一般是帶有絕對路徑的模塊文件名。
  • module.filename 模塊的文件名,帶有絕對路徑。
  • module.loaded 返回一個布爾值,表示模塊是否已經完成加載。
  • module.parent 返回一個對象,表示調用該模塊的模塊。
  • module.children 返回一個數組,表示該模塊要用到的其餘模塊。
  • module.exports 表示模塊對外輸出的值。

二、exportsthis

NodeJs 爲每一個模塊提供一個 exports 變量,指向 module.exports在使用的時候,能夠直接給 exports 添加屬性,就會指向 module.exports。可是不能給 exports 直接賦值一個變量,這樣會切斷 exportsmodule.exports 之間的聯繫。

若是有 exportsmodule.exportsexports 就會失效,只會輸出 module.exports 的,由於 module.exports 被從新賦值了。

三、global

這是一個全局變量聲明方式,就能夠全局用這個 warning 變量了。

global.warning = true;

四、require

require 命令用於加載模塊文件。

require 命令的基本功能是,讀入並執行一個 JavaScript 文件,而後返回該模塊的 exports 對象
加載規則:

  • 若是參數字符串以「/」開頭,則表示加載的是一個位於絕對路徑的模塊文件。
  • 若是參數字符串以「./」開頭,則表示加載的是一個位於相對路徑(跟當前執行腳本的位置相比)的模塊文件。
  • 若是參數字符串不以「./「或」/「開頭,則表示加載的是一個默認提供的核心模塊(位於Node的系統安裝目錄中),或者一個位於各級node_modules目錄的已安裝模塊(全局安裝或局部安裝)。
  • 若是參數字符串不以「./「或」/「開頭,並且是一個路徑,好比 require('example-module/path/to/file'),則將先找到 example-module 的位置,而後再以它爲參數,找到後續路徑。
  • 若是指定的模塊文件沒有發現,Node會嘗試爲文件名添加.js、.json、.node後,再去搜索。.js件會以文本格式的JavaScript腳本文件解析,.json文件會以JSON格式的文本文件解析,.node文件會以編譯後的二進制文件解析。
  • 若是想獲得 require 命令加載的確切文件名,使用 require.resolve() 方法。

require函數及其輔助方法主要以下。

  • require(): 加載外部模塊
  • require.resolve():將模塊名解析到一個絕對路徑
  • require.main:指向主模塊
  • require.cache:指向全部緩存的模塊
  • require.extensions:根據文件的後綴名,調用不一樣的執行函數

關於緩存:

在屢次加載某個相同的模塊時,若是前面的模塊已經操做了,後面調用時,拿到就再也不是最初時的數據了,就是通過前面操做事後的數據了。

全部緩存的模塊保存在 require.cache 之中,若是想刪除模塊的緩存,能夠像下面這樣寫。

// 刪除指定模塊的緩存
delete require.cache\[moduleName\];

// 刪除全部模塊的緩存
Object.keys(require.cache).forEach(function(key) {
 delete require.cache\[key\];
})

注意:緩存是根據絕對路徑識別模塊的,若是一樣的模塊名,可是保存在不一樣的路徑,require 命令仍是會從新加載該模塊。

1.3 模塊的加載機制

CommonJS 模塊的加載機制是,輸入的是被輸出的值的拷貝。也就是說,一旦輸出一個值,模塊內部的變化就影響不到這個值。

2、ES Module

2.1 概述

ES6 模塊的設計思想是儘可能的靜態化,使得編譯時就能肯定模塊的依賴關係,以及輸入和輸出的變量。因此ES6 模塊不是對象,而是經過 export 命令顯式指定輸出的代碼,再經過 import 命令輸入。這種加載稱爲「編譯時加載」或者靜態加載,即 ES6 能夠在編譯時就完成模塊加載,效率要比 CommonJS 模塊的加載方式高。固然,這也致使了無法引用 ES6 模塊自己,由於它不是對象。

2.2 ES Module的特色:

ES6 的模塊功能主要由兩個命令構成:exportimportexport 命令用於規定模塊的對外接口。import 命令用於輸入 其餘模塊提供的功能。

  • ES6 模塊必須用 export 導出
  • export 必須與模塊內部的變量創建一一對應關係

一、export命令

  • 一個模塊就是一個獨立的文件。該文件內部的全部變量,外部沒法獲取。若是你但願外部可以讀取模塊內部的某個變量,就必須使用 export 關鍵字輸出該變量。
  • export 命令規定的是對外的接口,必須與模塊內部的變量創建一一對應關係。

二、import命令

  • import 命令輸入的變量都是隻讀的
  • import 命令具備提高效果
  • import 是靜態執行,因此不能使用表達式和變量
  • import 語句是 Singleton 模式,若是屢次重複執行同一句 import 語句,那麼只會執行一次,而不會執行屢次。

三、export default 命令

  • export default 就是輸出一個叫作 default 的變量或方法
  • export default 因此它後面不能跟變量聲明語句

3、CommonJs 和 ES Module的區別

  • ES6 模塊輸出的是值的引用,CommonJS 模塊輸出的是一個值的拷貝
  • ES6 模塊是編譯時輸出接口,CommonJS 模塊是運行時加載。
  • ES6 模塊不是對象,它的對外接口只是一種靜態定義,在代碼靜態解析階段就會生成。而 CommonJS 加載的是一個對象(即 module.exports 屬性),該對象只有在腳本運行完纔會生成。
es6 {

 export : ‘能夠輸出多個,輸出方式爲 {}’ ,

 export default : ‘ 只能輸出一個 ,能夠與 export 同時輸出,可是不建議這麼作’,

 解析階段肯定對外輸出的接口,解析階段生成接口,

 模塊不是對象,加載的不是對象,

 能夠單獨加載其中的某個接口(方法),

 靜態分析,動態引用,輸出的是值的引用,值改變,引用也改變,即原來模塊中的值改變則該加載的值也改變,

 this 指向 undefined

}

  

commonJS {

 module.exports = … : ‘只能輸出一個,且後面的會覆蓋上面的’ ,

 exports. … : ‘ 能夠輸出多個’,

 運行階段肯定接口,運行時纔會加載模塊,

 模塊就是對象,加載的是該對象,

 加載的是整個模塊,即將全部的接口所有加載進來,

 輸出的是值的拷貝,即原來模塊中的值改變不會影響已經加載的該值,

 this 指向當前模塊

}
相關文章
相關標籤/搜索