對於模塊加載:ES6、CommonJS、AMD、CMD的區別
運行和編譯的概念
編譯包括編譯和鏈接兩步。
編譯,把源代碼翻譯成機器能識別的代碼或者某個中間狀態的語言。
比如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的是運行的結果,把結果賦值給某個變量。
- 通過require引入基礎數據類型時,屬於復制該變量。
- 通過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的區別