最近在看一些前端工程化知識,總結模組化相關而成此篇,其中僅詳細介紹commonjs和es6 modules
原始模組化
commonjscmdumd
es6 modules
模組輸出
commonjs輸出的是乙個值的拷貝,es6 模組輸出的是值的引用。
commonjs輸出的是乙個值的拷貝意味著,在commonjs匯出生成之後,再修改原模組中的值無法改變匯出物件的值
// lib/counter.js
var counter = 1;
function increment()
function decrement()
module.exports = ;
// src/main.js
var counter = require('../../lib/counter');
counter.increment();
console.log(counter.counter); // 1
es6 modules 輸出值的引用意味著,你仍可以通過修改原模組的值來修改匯出模組的值
// lib/counter.js
exportlet counter = 1;
exportfunction increment()
exportfunction decrement()
// src/main.js
import * as counter from'../../counter';
console.log(counter.counter); // 1
counter.increment();
console.log(counter.counter); // 2
載入時機
因為 commonjs 載入的是乙個物件(module.exports),物件只有在有指令碼執行的時候才能生成。而 es6 模組不是乙個物件,只是乙個靜態的定義。在**解析階段就會生成。
es6 模組是編譯時輸出介面,因此有如下2個特點:
// a.js
console.log('a.js')
import from'./b';
// b.js
exportlet foo = 1;
console.log('b.js 先執行');
// 執行結果:
// b.js 先執行
// a.js
迴圈載入的差異
在 commonjs 中,指令碼**在 require 的時候,就會全部執行。一旦出現某個模組被"迴圈載入",就只輸出已經執行的部分,還未執行的部分不會輸出。
es6 處理「迴圈載入」與 commonjs 有本質的不同。es6 模組是動態引用,如果使用import從乙個模組載入變數(即import foo from 'foo'),那些變數不會被快取,而是成為乙個指向被載入模組的引用,需要開發者自己保證,真正取值的時候能夠取到值。
commonjs:
// a.js
exports.done = false;
var b = require('./b.js');
console.log('在 a.js 之中,b.done = %j', b.done);
exports.done = true;
console.log('a.js 執行完畢');
// b.js
exports.done = false;
var a = require('./a.js');
console.log('在 b.js 之中,a.done = %j', a.done);
exports.done = true;
console.log('b.js 執行完畢');
// main.js
var a = require('./a.js');
var b = require('./b.js');
console.log('在 main.js 之中, a.done=%j, b.done=%j', a.done, b.done);
//輸出結果
在 b.js 之中,a.done = false
b.js 執行完畢
在 a.js 之中,b.done = true
a.js 執行完畢
在 main.js 之中, a.done=true, b.done=true
從上面我們可以看出:
在b.js之中,a.js沒有執行完畢,只執行了第一行。
main.js執行到第二行時,不會再次執行b.js,而是輸出快取的b.js的執行結果,即它的第四行
es6 modules:
// a.mjs
import from'./b';
console.log('a.mjs');
console.log(bar);
exportlet foo = 'foo';
// b.mjs
import from'./a';
console.log('b.mjs');
console.log(foo);
exportlet bar = 'bar';
//執行結果
b.mjs
referenceerror: foo is not defined
具體的執行結果如下:
執行a.mjs以後,引擎發現它載入了b.mjs,因此會優先執行b.mjs,然後再執行a.mjs
執行b.mjs的時候,已知它從a.mjs輸入了foo介面,這時不會去執行a.mjs,而是認為這個介面已經存在了,繼續往下執行。
執行到第三行console.log(foo)的時候,才發現這個介面根本沒定義,因此報錯。
意思是,已載入過的(即使沒載入完),就會認為其已載入完,並呼叫模組輸出的引用拷貝
前端模組化
前端模組化解決什麼問題?有了模組,我就可以很方便的使用別人的 想要什麼功能,就用載入什麼模組。但是,這樣做需要有乙個前提,那就是大家必須以同樣的方式編寫模組,否則就亂套了。所以組內需要有一套統一的模組規範。如何實現模組?1 物件字面量的變體 2 js設計模式的模組模式 3 採用成熟的庫檔案。前兩種方...
前端模組化
定義 具有相同屬性和行為的事物的集合 在前端中 將一些屬性比較類似和行為比較類似的內容放在同乙個js檔案裡面,把這個js檔案稱為模組 目的 為了每個js檔案只關注與自身有關的事情,讓每個js檔案各行其職 模組化 指的就是遵守commonjs規範,解決不同js模組之間相互呼叫問題 commonjs a...
前端模組化
當多人開發同一專案時,很容易就會產生命名衝突的問題,尤其是js檔案,任何的js引入順序的打亂都可能導致專案執行失敗,為了解決命名衝突的問題,在es6之前,可以使用函式閉包來解決這個問題。即可能像這樣 function 這樣雖然可以解決命名衝突的問題,但也使得 的復用性變得極差,因為其它的檔案將無法再...