一、模塊化的理解
1.什么是模塊?
將一個復雜的程序依據一定的規則封裝成幾個塊(文件),並進行組合在一起。塊的內部數據與實現是私有的,只是向外部暴露一些借口(方法)與其他模塊通信
2.模塊化的進化過程
3.模塊化的好處
(1)避免命名沖突(減少命名空間污染)
(2)更好的分離,按需加載
(3)高復用性
(4)高可維護性
二、比較常用的三種規范定義:CommonJS、AMD、CMD
1.CommonJS適用於服務端
ex: var clock = require('clock.js'); clock.start();
clock調用必須等clock.js請求加載成功,是同步操作;當請求加載卡頓或失敗,客戶端有可能會出現假死。
2.AMD異步加載模塊,多用於瀏覽器
ex: require(['clock.js'])
雖然實現了異步加載,規避了瀏覽器的假死問題,但是也存在缺點:一開始就把所有以來寫出來是不符合邏輯順序的。
3.CMD則是以來就近,用的時候再require
ex: define(function(require,export,module){ var clock = require('clock.js'); clock.start(); })
三者區別
AMD和CMD的 區別是對依賴模塊的執行時機不同,二者皆為異步加載模塊。
AMD依賴前置,js可以方便地清晰依賴模塊有哪些,立即加載。
CMD就近依賴,開發者可以在需要用到依賴的時候再require,但是對於js處理器來說,需要把代碼處理為字符串解析一遍才知道依賴了哪些模塊,即犧牲性能來獲得開發的便利,雖然實際上解析的時間短到可以忽略,但是也有很多人詬病。
ES6的模塊化思想是盡量靜態化,使得編譯的時就能確定模塊的依賴關系。
CommonJS的實質是整體加載fs模塊生成一個_fs對象,之后再從對象中分別讀取3個方法,稱為“運行時加載”。而ES6模塊是加載3個方法,稱為“編譯時加載”。
ES6模塊化的語法規范
嚴格模式:
1.變量必須先聲明
2.函數參數不能有同名屬性
3.不能使用with
4.對只讀屬性賦值,delete不可刪除屬性直接報錯
5.不可刪除變量delete prop,只能刪除屬性delete global[prop]
6.eval不會在外層作用域引入變量
7.eval和arguments不可重新賦值
8.arguments不會自動反應函數參數變化
9.禁止this指向全局
10.增加保留關鍵字:static \ interface \ protectes等
注意:ES6中,頂層this為undefined,不應被使用
export命令(注意):
1.export語句輸出的接口是對應值的引用,也就是一種動態綁定關系,通過該接口可以獲取 模塊內部實時的值,CommonJS模塊輸出的是值得緩存,不存在動態更新
2.export命令規定要處於模塊頂層,一旦出現在塊級作用域內就會報錯,import同理
import命令:
1.import是靜態執行,不可以應用表達式 、變量和 if 結構
2.import語句是singleton模式——雖然 foo 和 bar 在兩個語句中加載,但對應同一個實例
ex: import { foo } as foo from 'example';
imort { bar } as bar from 'example';
模塊的整體加載:
可以使用 * 來制定一個對象,所有輸出值都加載到這個對象上。
ex: import * as cirde from './modeule';
由於模塊整體加載所在的對象都是可以靜態分析的,所以不允許運行時改變
cirde.foo()調用foo可以,cirde.foo = 123;運行時給foo重賦值不允許
默認輸出:
export default 命令可以為模塊默認輸出
ex: export default function () { console.log(123); }
import 命令可以為匿名函數制定任意名字
ex: import default from './modeule'
import() 方法:
require 是動態加載,可以在用的時候再require;而import是靜態執行,只能處於代碼最頂層,不可以存在於塊級作用域中。
定義:import()函數接收與import相同的參數 返回一個Promise對象,加載獲取到的值作為then()方法的回調參數