1. 程式人生 > >對於模塊加載:ES6、CommonJS、AMD、CMD的區別

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

內存 imp 之前 readfile 分開 sil 但是 基礎 從服務器

運行和編譯的概念

編譯包括編譯和鏈接兩步。

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

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

鏈接,是把編譯生成的二進制文件,組合成為一個系統可以執行的可執行文件。

運行:

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

(代碼保存在磁盤上沒裝入內存之前是個死家夥.只有跑到內存中才變成活的).

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

模塊的加載

ES6、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。

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‘

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