對於模塊加載:ES六、CommonJS、AMD、CMD的區別

運行和編譯的概念

編譯包括編譯和連接兩步。html

編譯,把源代碼翻譯成機器能識別的代碼或者某個中間狀態的語言。vue

好比java只有JVM識別的字節碼,C#中只有CLR能識別的MSIL。還簡單的做一些好比檢查有沒有粗心寫錯啥關鍵字了啊.有啥詞法分析,語法分析之類的過程。java

連接,是把編譯生成的二進制文件,組合成爲一個系統能夠執行的可執行文件。node

 

運行:es6

把編譯出來的可執行文件代碼在系統中執行的過程,此時被裝載到內存中編程

(代碼保存在磁盤上沒裝入內存以前是個死傢伙.只有跑到內存中才變成活的).瀏覽器

運行時類型檢查就與前面講的編譯時類型檢查(或者靜態類型檢查)不同.不是簡單的掃描代碼.而是在內存中作些操做,作些判斷.緩存

模塊的加載

ES六、CommonJS、AMD、CMD指的都是一種規範。服務器

CommonJS

爲在瀏覽器環境以外構建JavaScript生態系統而產生的項目,好比服務器和桌面環境中。異步

一個單獨的文件就是一個模塊,代碼都運行在模塊做用域,若是想在多個文件分享變量,必須定義爲global對象的屬性。(不推薦)

//模塊內部,module變量表明當前模塊,它的exports屬性是對外的接口
//其餘文件加載該模塊,實際上就是讀取module.exports變量。
var x = 5;
var addX = function (value) {
  return value + x;
};
module.exports.x = x;
module.exports.addX = addX;
//PS:不能直接對module.exports賦值,只能給它添加方法或者屬性

加載機制:

模塊可屢次加載,但模塊的運行只在第一次加載時,運行結果被緩存了,之後再加載,就直接讀取緩存結果。

經過require()同步加載依賴,導出API輸出到當前模塊,多個模塊不能並行加載。

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

應用:

服務器端的Node.js遵循CommonJS規範,Node.js主要用於服務器的編程,加載的模塊文件通常都已經存在本地硬盤,因此加載起來比較快,不用考慮異步加載的方式,因此CommonJS規範比較適用。

 

若是是瀏覽器環境,要從服務器加載模塊,這是就必須採用異步模式。因此就有了 AMD 、CMD 的解決方案,AMD與CMD都借鑑了CommonJs

AMD 、CMD

AMD(Asynchronous Module Definition)異步模塊加載,AMD 裏,require 分全局 require 和局部 require。

CMD(Common Module Definition) 通用模塊加載,提供模塊定義及按需執行模塊。CMD 裏,沒有全局 require,而是根據模塊系統的完備性,提供 seajs.use 來實現模塊系統的加載啓動

優劣:

AMD | 速度快 | 會浪費資源 | 預先加載全部的依賴,直到使用的時候才執行
CMD | 只有真正須要才加載依賴 | 性能較差 | 直到使用的時候才定義依賴

AMD:

define(['./a', './b'], function(a, b) { //運行至此,a.js和b.js文件已下載完成 a模塊和b模塊已執行完,直接可用;
    a.doing();
    // 此處省略500行代碼
    b.doing();
});

CMD:

define(function(require, exports, module) {
     var a = require("./a"); //等待a.js下載、執行完
     a.doing();
     // 此處省略500行代碼
     var b = require("./b"); //依賴就近書寫
     b.doing();
});

 ES6

使用export或export default導出,import導入。

import是編譯時調用,因此不能使用表達式和變量,這些只有在運行時才能獲得結果的語法結構。

import是解構過程,本質是輸入接口,不容許在加載模塊的腳本里面,改寫接口。

import命令具備提高效果,會提高到整個模塊的頭部,首先執行。

import語句會執行所加載的模塊,所以能夠有下面的寫法。

import 'lodash';

上面代碼僅僅執行lodash模塊,可是不輸入任何值。

屢次重複執行同一句import語句,那麼只會執行一次。

 

在一個模塊之中,先輸入後輸出同一個模塊,export和import語句能夠結合在一塊兒,寫成一行:

export { foo, bar } from 'my_module';

// 能夠簡單理解爲
import { foo, bar } from 'my_module';
export { foo, bar };

注意的是,foobar實際上並無被導入當前模塊,只是至關於對外轉發了這兩個接口,致使當前模塊不能直接使用foobar

export與export default的區別:

1.export與export default都可用於導出常量、函數、文件、模塊等
2.在一個文件或模塊中,export、import能夠有多個,export default僅有一個
3.經過export方式導出,在導入時要加{ },export default則不須要

4. 

(1)模塊輸出單個值,使用export default

(2) 模塊輸出輸出多個值,使用export

(3) export default與普通的export不要同時使用

//a.js  export
export const str = "blablabla~";
export function log(sth) { 
  return sth;
}

//b.js  import
import { str, log } from 'a'; //也能夠分開寫兩次,導入的時候帶花括號


//a.js  export default
const str = "blablabla~";
export default str;


//b.js  import
import str from 'a'; //導入的時候沒有花括號

//本質上,a.js文件的export default輸出一個叫作default的變量,而後系統容許你爲它取任意名字。因此能夠爲import的模塊起任何變量名,且不須要用大括號包含

import和require的區別

vue模塊引入使用import,node模塊引入使用require

遵循規範

  • require 是 AMD規範引入方式
  • import是es6的一個語法標準,若是要兼容瀏覽器的話必須轉化成es5的語法(最好去看文檔

加載

  • require是運行時調用在運行時肯定模塊的依賴關係,獲得模塊對象及輸入/輸出的變量,沒法進行靜態優化。因此require的是運行的結果,把結果賦值給某個變量。
    1. 經過require引入基礎數據類型時,屬於複製該變量。
    2. 經過require引入複雜數據類型時,數據淺拷貝該對象。
  • import是編譯時調用,支持編譯時靜態分析,不須要的方法就不會加載,便於JS引入宏和類型檢驗,不能包含運行才知道結果的表達式等

寫法

require / exports :

const fs = require('fs')
exports.fs = fs
module.exports = fs

import / export:

import fs from 'fs'
import {default as fs} from 'fs'
import * as fs from 'fs'
import {readFile} from 'fs'
import {readFile as read} from 'fs'
import fs, {readFile} from 'fs'

export default fs
export const fs
export function readFile
export {readFile, read}
export * from 'fs'
相關文章
相關標籤/搜索