成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

前端模塊化

liukai90 / 352人閱讀

摘要:如果想讓模塊再次執(zhí)行,必須清楚緩存同步加載模塊只有加載完成之后,才能執(zhí)行后面的操作運(yùn)行時(shí)加載中的實(shí)現(xiàn)對(duì)象中提供了一個(gè)構(gòu)造函數(shù),每個(gè)模塊都是構(gòu)造函數(shù)的實(shí)例。

什么是模塊化 1、模塊化

模塊化是自頂向下逐層將系統(tǒng)劃分成若干更好的可管理模塊的方式,用來(lái)分割、組織和打包軟件,達(dá)到高度解耦

2、模塊

模塊是可組合、分解、更換的單元;
每個(gè)模塊完成一個(gè)特定子功能,模塊間通過(guò)某種方式組裝起來(lái),成為一個(gè)整體
模塊間高度解耦,模塊功能單一,可高度復(fù)用

3、前端模塊化解決的問(wèn)題

1、消除全局變量,減少命名沖突
2、更好地代碼組織結(jié)構(gòu)和開發(fā)協(xié)作:通過(guò)文件拆分,更易于管理復(fù)雜代碼庫(kù),更易于多人協(xié)作開發(fā),降低文件合并時(shí)候沖突的發(fā)生概率,方便編寫單元測(cè)試
3、依賴管理、按需加載:不再需要手動(dòng)管理腳本加載順序
4、優(yōu)化:
(1)代碼打包:合并小模塊,抽取公共模塊,在資源請(qǐng)求數(shù)和瀏覽器緩存利用方面進(jìn)行合適的取舍
(2)代碼分割:按需加載代碼(分路由、異步組件),解決單頁(yè)面應(yīng)用首屏加載緩慢的問(wèn)題
(3)Tree Shaking :利用ES6模塊的靜態(tài)化特性。在構(gòu)建過(guò)程中分析出代碼庫(kù)中未使用的代碼,從最終的bundle中 去除,從而減少JS Bundle的大小
(4)Scope Hoisting:ES6模塊內(nèi)容導(dǎo)入導(dǎo)出綁定是活動(dòng)的,可以將多個(gè)小模塊合并到一個(gè)函數(shù)當(dāng)中去,對(duì)于重復(fù)變量名進(jìn)行核實(shí)的重命名,從而減少Bundle的尺寸和提升加載速度。

前端為什么需要模塊化(模塊的發(fā)展) 1、內(nèi)嵌腳本---原始寫法

1.1語(yǔ)法

標(biāo)記之間添加js代碼 ,把不同的函數(shù)等簡(jiǎn)單放在一起,就算是一個(gè)模塊

    function fn1(){....}
?
    function fn2(){....}

1.2不足

代碼無(wú)重用性:其他頁(yè)面需要該script標(biāo)簽中一些代碼時(shí),需要復(fù)制粘貼
全局命名空間污染:所有變量、方法等都定義在全局作用域中,也容易命名沖突

2、外鏈腳本---原始寫法

2.1語(yǔ)法

將js代碼分成多個(gè)片段分別放入s文件中,使用 ? ? ?

2.2不足

缺乏依賴管理:文件之間講究先后順序,互相之間存在依賴關(guān)系
全局命名空間污染:所有變量、方法等都定義在全局作用域中

3、對(duì)象封裝

一個(gè)對(duì)象就是一個(gè)模塊,所有模塊成員都在其中

3.1語(yǔ)法

var obj = new Object({
    fn1 : function (){},
    fn2 : function (){}
    .....
});

3.2不足

暴露了內(nèi)部成員:所以內(nèi)部成員都被暴露,在外不可以輕易被修改
缺乏依賴管理:一個(gè)模塊一個(gè)文件,文件順序還需要手動(dòng)控制
全局命名空間污染:仍然需要暴露一個(gè)全局變量

4、結(jié)合對(duì)象封裝與IIFE(立即執(zhí)行函數(shù)表達(dá)式)

4.1 語(yǔ)法

將每個(gè)文件都封裝成IIFE,內(nèi)部定義的變量和方法只在IIFE作用域內(nèi)生效,不會(huì)污染全局。并且通過(guò)將這些方法變量賦值給某個(gè)全局對(duì)象來(lái)公開 , 不暴露私有成員;

var module = (function(obj){
    let a =1;
    obj.fn1=function (){}
    return obj
})(module || {});

4.2 應(yīng)用

Jquery庫(kù),公開一個(gè)全局對(duì)象$, 它中包含所以方法與屬性

4.3 不足

缺乏依賴管理:文件順序還需要手動(dòng)控制,例如使用jQuery的方法前,必須保證jQuery已經(jīng)加載完
全局命名空間污染:仍然需要暴露一個(gè)全局變量

5、模塊化規(guī)范的出現(xiàn)
(1) js引入服務(wù)器端后,出現(xiàn)的 CommonJS規(guī)范
(2)CommonJS的同步性限制了前端的使用,出現(xiàn)了 AMD
(3)UMD規(guī)范的統(tǒng)一
(4)ES6模塊的定義

CommonJs 與 nodeJs服務(wù)端的模塊化實(shí)現(xiàn)

CommonJS是除瀏覽器之外 構(gòu)建js生態(tài)系統(tǒng)為目標(biāo)而產(chǎn)生的規(guī)范,比如服務(wù)器和桌面環(huán)境等。最早 由Mozilla的工程師Kevin Dangoor在2009年1月創(chuàng)建。

2013年5月,Node.js 的包管理器 NPM 的作者 Isaac Z. Schlueter 說(shuō) CommonJS 已經(jīng)過(guò)時(shí),Node.js 的內(nèi)核開發(fā)者已經(jīng)廢棄了該規(guī)范。

1、定義

每個(gè)文件是一個(gè)模塊,有自己的作用域。在一個(gè)文件里定義的變量、函數(shù)等都是私有的,對(duì)其他文件不可見(jiàn)。

在每個(gè)模塊內(nèi)部,module變量代表當(dāng)前模塊,它的exports屬性是對(duì)外的接口,加載某個(gè)模塊(require)時(shí),其實(shí)加載的是該模塊的 exports屬性

var x = 5;
var addX = function (value) {
  return value + x;
};
module.exports.x = x;
module.exports.addX = addX;
2、語(yǔ)法

CommonJS包含主要包含三部分:模塊導(dǎo)入(加載),模塊定義、模塊標(biāo)識(shí)

2.1 模塊導(dǎo)入:require() ——返回該模塊的exports屬性

var  module1 = require("./module1.js");

2.2 模塊定義 :module.exports

//module1.js
module.exports.fn1 = function (){}

2.3 模塊標(biāo)識(shí):require()方法的參數(shù)

必須是字符串
可以是以./ ../開頭的相對(duì)路徑
可以是絕對(duì)路徑
可以省略后綴名

3、特點(diǎn)

自動(dòng)依賴管理:模塊加載的順序 依賴于其在代碼中出現(xiàn)的順序
不污染全局作用域:模塊內(nèi)部代碼運(yùn)行在自己的私有作用域
可多次加載,但只執(zhí)行一次:模塊可以多次加載,但是只會(huì)在第一次加載時(shí)運(yùn)行一次,然后運(yùn)行結(jié)果被緩存,以后再加載,直接讀取緩存結(jié)果。如果想讓模塊再次執(zhí)行,必須清楚緩存
同步加載模塊:只有加載完成之后,才能執(zhí)行后面的操作
運(yùn)行時(shí)加載

4、nodejs中的實(shí)現(xiàn)

4.1 module對(duì)象

node中提供了一個(gè)Module構(gòu)造函數(shù),每個(gè)模塊都是構(gòu)造函數(shù)的實(shí)例。每個(gè)模塊內(nèi)部,都要一個(gè)module對(duì)象,代表當(dāng)前模塊

      //Module構(gòu)造函數(shù)
        function Module(id,parent){
            this.id=id;//模塊的標(biāo)識(shí)符,通常為帶有絕對(duì)路徑的模塊文件名
            this.exports ={};//模塊暴露出去的方法或者變量
            this.parent=parent;//返回一個(gè)對(duì)象,父級(jí)模塊,調(diào)用該模塊的模塊
            if(parent && parent.children){
                parent.children.push(this); 
            }
    ?
            this.filename =null;//模塊文件名,帶有絕對(duì)路徑
           this.loaded=false;//返回一個(gè)布爾值,該模塊是否加載完成(因?yàn)槭沁\(yùn)行時(shí)加載,所以代表是否已經(jīng)執(zhí)行完畢)
            this.chilren =[];//返回?cái)?shù)組,該模塊要用到的其他模塊
        }

?
    //實(shí)例化一個(gè)模塊
    var module1 =new Module(filename,parent)

4.2 module.exports屬性

module.exports屬性表示當(dāng)前模塊對(duì)外輸出的接口,其他文件加載該模塊,實(shí)際上就是讀取module.exports變量。

4.3 exports變量

node為每個(gè)模塊提供了exoprts變量,指向module.exports。等同于在每個(gè)模塊頭部,有一行代碼

var exports = module.exports;

在對(duì)外輸出時(shí),可以向exports對(duì)象添加方法

exports.fn1 =function(){}

不能直接將exports指向一個(gè)值,這樣會(huì)切斷exports與module.exports的聯(lián)系

exports = function(x) {console.log(x)};

如果一個(gè)模塊的module.exports是一個(gè)單一的值,不能使用exports輸出,只能使用module.exports輸出

//hello函數(shù)是無(wú)法對(duì)外輸出的,因?yàn)閙odule.exports被重新賦值了。

exports.hello = function() {
  return "hello";
};
?
module.exports = "Hello world";

?
4.4 node中的模塊分類

node中模塊分為兩類:一類為mode提供的核心模塊,另一類為 用戶編寫的文件模塊

4.4.1 核心模塊

即node提供的內(nèi)置模塊如 http模塊、url模塊、fs模塊等

核心模塊在node源代碼的編譯過(guò)程中被編譯進(jìn)了二進(jìn)制文件,在node進(jìn)程啟動(dòng)的時(shí)候,會(huì)被直接加載進(jìn)內(nèi)存,因此引用這些模塊的時(shí)候,文件定位和編譯執(zhí)行這兩步會(huì)被省略。

在路徑分析中會(huì)優(yōu)先判斷核心模塊,加載速度最快。

4.4.2 文件模塊

即外部引入的模塊 如node_modules中的模塊,項(xiàng)目中自己編寫的js文件等

在運(yùn)行時(shí)動(dòng)態(tài)加載,需要完整的路徑分析,文件定位,編譯執(zhí)行這三部,加載速度比核心模塊慢

4.5 路徑分析、文件定位、編譯執(zhí)行

4.5.1路徑分析

不論核心模塊還是文件模塊都需要經(jīng)歷路徑分析這一步,Node支持如下幾種形式的模塊標(biāo)識(shí)符,來(lái)引入模塊:

//核心模塊
require("http")
----------------------------
//文件模塊
?
//以.開頭的相對(duì)路徑,(可以不帶擴(kuò)展名)
require("./a.js")
  
//以..開頭的相對(duì)路徑,(可以不帶擴(kuò)展名)
require("../b.js")
?
//以/開始的絕對(duì)路徑,(可以不帶擴(kuò)展名)
require("/c.js")
?
//外部模塊名稱
require("express")
?
//外部模塊某一個(gè)文件
require("codemirror/addon/merge/merge.js");

● Node 會(huì)優(yōu)先去內(nèi)存中查找匹配核心模塊,如果匹配成功便不會(huì)再繼續(xù)查找
(1)比如require http 模塊的時(shí)候,會(huì)優(yōu)先從核心模塊里去成功匹配
● 如果核心模塊沒(méi)有匹配成功,便歸類為文件模塊
(2) 以.、..和/開頭的標(biāo)識(shí)符,require都會(huì)根據(jù)當(dāng)前文件路徑將這個(gè)相對(duì)路徑或者絕對(duì)路徑轉(zhuǎn)化為真實(shí)路徑,也就是我們平時(shí)最常見(jiàn)的一種路徑解析
(3)非路徑形式的文件模塊 如上面的"express" 和"codemirror/addon/merge/merge.js",這種模塊是一種特殊的文件模塊,一般稱為自定義模塊。

4.5.1.1 模塊路徑

自定義模塊的查找最費(fèi)時(shí),因?yàn)閷?duì)于自定義模塊有一個(gè)模塊路徑,Node會(huì)根據(jù)這個(gè)模塊路徑依次遞歸查找。
模塊路徑——Node的模塊路徑是一個(gè)數(shù)組,模塊路徑存放在module.paths屬性上。
我們可以找一個(gè)基于npm或者yarn管理項(xiàng)目,在根目錄下創(chuàng)建一個(gè)test.js文件,內(nèi)容為console.log(module.paths),如下:

//test.js
console.log(module.paths);
然后在根目錄下用Node執(zhí)行

node test.js
可以看到我們已經(jīng)將模塊路徑打印出來(lái)。

可以看到模塊路徑的生成規(guī)則如下:
● 當(dāng)前路文件下的node_modules目錄
● 父目錄下的node_modules目錄
● 父目錄的父目錄下的node_modules目錄
● 沿路徑向上逐級(jí)遞歸,直到根目錄下的node_modules目錄
對(duì)于自定義文件比如express,就會(huì)根據(jù)模塊路徑依次遞歸查找。
在查找同時(shí)并進(jìn)行文件定位。

4.5.2文件定位

● 擴(kuò)展名分析
我們?cè)谑褂胷equire的時(shí)候有時(shí)候會(huì)省略擴(kuò)展名,那么Node怎么定位到具體的文件呢?
這種情況下,Node會(huì)依次按照.js、.json、.node的次序一次匹配。(.node是C++擴(kuò)展文件編譯之后生成的文件)
若擴(kuò)展名匹配失敗,則會(huì)將其當(dāng)成一個(gè)包來(lái)處理,我這里直接理解為npm包

● 包處理
對(duì)于包Node會(huì)首先在當(dāng)前包目錄下查找package.json(CommonJS包規(guī)范)通過(guò)JSON.parse( )解析出包描述對(duì)象,根據(jù)main屬性指定的入口文件名進(jìn)行下一步定位。
如果文件缺少擴(kuò)展名,將根據(jù)擴(kuò)展名分析規(guī)則定位。
若main指定文件名錯(cuò)誤或者壓根沒(méi)有package.json,Node會(huì)將包目錄下的index當(dāng)做默認(rèn)文件名。
再依次匹配index.js、index.json、index.node。
若以上步驟都沒(méi)有定位成功將,進(jìn)入下一個(gè)模塊路徑——父目錄下的node_modules目錄下查找,直到查找到根目錄下的node_modules,若都沒(méi)有定位到,將拋出查找失敗的異常。

4.5.3模塊編譯

● .js文件——通過(guò)fs模塊同步讀取文件后編譯執(zhí)行
● .node文件——用C/C++編寫的擴(kuò)展文件,通過(guò)dlopen( )方法加載最后編譯生成的文件。
● .json——通過(guò)fs模塊同步讀取文件后,用JSON.parse( ) 解析返回結(jié)果。
● 其余擴(kuò)展名文件。它們都是被當(dāng)做.js文件載入。

每一個(gè)編譯成功的文件都會(huì)將其文件路徑作為索引緩存在Module._cache對(duì)象上,以提高二次引入的性能。
這里我們只講解一下JavaScript模塊的編譯過(guò)程,以解答前面所說(shuō)的CommonJS模塊中的require、exports、module變量的來(lái)源。

我們還知道Node的每個(gè)模塊中都有filename、dirname 這兩個(gè)變量,是怎么來(lái)的的呢?
其實(shí)JavaScript模塊在編譯過(guò)程中,整個(gè)所要加載的腳本內(nèi)容,被放到一個(gè)新的函數(shù)之中,這樣可以避免污染全局環(huán)境。該函數(shù)的參數(shù)包括require、module、exports,以及其他一些參數(shù)。
Node對(duì)獲取的JavaScript文件內(nèi)容進(jìn)行了頭部和尾部的包裝。在頭部添加了(function (exports, require, module,filename, dirname){n,而在尾部添加了n}); 。

因此一個(gè)JS模塊經(jīng)過(guò)編譯之后會(huì)被包裝成下面的樣子:

(function(exports, require, module, __filename, __dirname){
  var express = require("express") ;
  exports.method = function (params){
   ...
  };
});

4.6 模塊加載機(jī)制

整體加載執(zhí)行,導(dǎo)入的是被輸出的值得拷貝,即 一旦輸出一個(gè)值,模塊內(nèi)部的變化就影響不到這個(gè)值

// lib.js
var counter = 3;
function incCounter() {
  counter++;
}
module.exports = {
  counter: counter,
  incCounter: incCounter,
};
?
?
?
?
// main.js
var counter = require("./lib").counter;
var incCounter = require("./lib").incCounter;
?
console.log(counter);  // 3
incCounter();
console.log(counter); // 3 
//counter輸出以后,lib.js模塊內(nèi)部的變化就影響不到counter了。

4.7 require 的內(nèi)部處理流程

require不是一個(gè)全局命令,而是指向當(dāng)前模塊的module.require命令,module.require又調(diào)用node內(nèi)部命令Module._load

require —>module.require——>Module._load

MOdule._load =function(require,parent,isMain){
    1.檢查緩存Module._cache ,是否有指定模塊
    2.如果緩存中沒(méi)有,就創(chuàng)建一個(gè)新的MOdule實(shí)例
    3.將實(shí)例保存到緩存
    4.使用Module,load()加載指定的模塊文件
    5.讀取文件內(nèi)容后,使用module.compile()執(zhí)行文件代碼
    6.如果加載/解析過(guò)程報(bào)錯(cuò),就從緩存中刪除該模塊
    7.返回該模塊的module.exports
}

Module.compile方法是同步執(zhí)行的,所有Module.load 要等它執(zhí)行完成,才會(huì)向用戶返回 module.exports的值

AMD 與 requireJs

由于node主要用戶服務(wù)端編程,模塊文件一般都已經(jīng)存在于本地硬盤,所以加載起來(lái)比較快,不用考慮非同步加載的方式,因此CommonJS規(guī)范比較適用。但是如果是瀏覽器環(huán)境,要從服務(wù)器端加載資源,這時(shí)就必須采用非同步模式。

1、模塊定義
define(id? dependencies?,factory)

id為string類型,表示模塊標(biāo)識(shí)
dependencies:為Array類型,表示需要依賴的模塊
factory:為function或者Object,表示要進(jìn)行的回調(diào)

1.1 獨(dú)立模塊(不需要依賴模塊)

define({
    fn1:function(){}
 })
?
define(function(){
    return {
        fn1:function(){},   
    }
})

1.2 非獨(dú)立模塊(有依賴其他模塊)

define(["module1","module2"],function(){})   //  依賴必須一開始就寫好
2、模塊導(dǎo)入

require(["a","b"],function(a,b){})

3、特點(diǎn)

依賴管理:被依賴的文件早于主邏輯被加載執(zhí)行 ;
運(yùn)行時(shí)加載;
異步加載模塊:在模塊的加載過(guò)程中即使require的模塊還沒(méi)有獲取到,也不會(huì)影響后面代碼的執(zhí)行,不會(huì)阻塞頁(yè)面渲染

4、RequireJS

AMD規(guī)范是RequireJS在推廣過(guò)程中對(duì)模塊定義的規(guī)范化產(chǎn)出

CMD 與 seajs 1、模塊定義

在依賴示例部分,CMD支持動(dòng)態(tài)引入,require、exports和module通過(guò)形參傳遞給模塊,在需要依賴模塊時(shí),隨時(shí)調(diào)用require( )引入即可,示例如下:

define(factory)

1.1 factory 三個(gè)參數(shù)

function(require,exports,module)
require用于導(dǎo)入其他模塊接口
exports 用于導(dǎo)出接口
module存儲(chǔ)了與當(dāng)前模塊相關(guān)聯(lián)的一些屬性與方法

1.2 例子

define(function(require ,exports,module) {
    //調(diào)用依賴模塊increment的increment方法
    var inc = require("increment").increment;   // 依賴可以就近書寫
    var a = 1;
    inc(a); 
    module.id == "program"; 
});
2、模塊導(dǎo)入
require("路徑")  
3、特點(diǎn)

依賴就近書寫:一般不再define的參數(shù)中寫依賴,就近書寫
延遲執(zhí)行

UMD通用規(guī)范

兼容CommonJS、AMD 、CMD、全局引用
寫法:

(function(global,factory){
    typeof exports === "object"&& typeof module!=="undefined"
    ?module.exports =factory()   //CommonJS
    :typeof define ==="fucntion" && define.amd
    ?define(factory)         //AMD CMD
    :(global.returnExports = factory()) //掛載到全局
}(this,function(){
    //////暴露的方法
    return fn1
}))
es6 module 1、模塊導(dǎo)出 export

export 輸入變量、函數(shù)、類等 與模塊內(nèi)部的變量建立一一對(duì)應(yīng)關(guān)系

//寫法一   
export var a=1;
//寫法二
var a=1;
export {a}
//寫法三  as進(jìn)行重命名
var b=1; 
export {b as a}
//寫法四
var a=1
export default a 

export語(yǔ)句輸出的接口,與其對(duì)應(yīng)的值是動(dòng)態(tài)綁定關(guān)系,即通過(guò)該接口,可以取到模塊內(nèi)部實(shí)時(shí)的值。

export var foo = "bar";
setTimeout(() => foo = "baz", 500);

上面代碼輸出變量foo,值為bar,500 毫秒之后變成baz。

2、模塊輸入 import

2.1 寫法一

import命令接受一對(duì)大括號(hào),里面指定要加載指定模塊,并從中輸入變量

import {firstName, lastName, year} from "./profile.js";
import { lastName as surname } from "./profile.js";

大括號(hào)里面的變量名,必須與被導(dǎo)入模塊(profile.js)對(duì)外接口的名稱相同。
可以使用as關(guān)鍵字,將輸入的變量重命名。

2.2 寫法二

import 后面寫模塊路徑--------執(zhí)行所加載的模塊,但不輸入任何值

import "lodash";

上面代碼僅僅執(zhí)行l(wèi)odash模塊,但是不輸入任何值。
如果多次重復(fù)執(zhí)行同一句import語(yǔ)句,那么只會(huì)執(zhí)行一次,而不會(huì)執(zhí)行多次。

2.3 寫法三

用星號(hào)(*)指定一個(gè)對(duì)象,整體加載所有對(duì)象到這個(gè)對(duì)象上 ——整體模塊加載

import * as circle from "./circle";

2.4 export default 與 import

export default 實(shí)際導(dǎo)出的為一個(gè)叫做 default 的變量,所以其后面不能跟變量聲明語(yǔ)句
使用export default命令時(shí),import是不需要加{}的
不使用export default時(shí),import是必須加{}

//person.js
export function getName() {
 ...
}
//my_module
import {getName} from "./person.js";
?
?
?
//person.js
export default function getName(){
 ...
}
//my_module
import getName from "./person.js";
?
?
//person.js
export name = "dingman";
export default function getName(){
  ...
}
?
//my_module
import getName, { name } from "./person.js";
3、特點(diǎn)

編譯時(shí)加載:編譯的時(shí)候就可以確定模塊的依賴關(guān)系,已經(jīng)輸入與輸出的變量

各規(guī)范總結(jié) 1、 CommonJS

環(huán)境:服務(wù)器環(huán)境
特點(diǎn):(1)同步加載;(2)運(yùn)行時(shí)加載 (3)多次加載,只第一次執(zhí)行,以后直接讀取緩存
應(yīng)用: Nodejs
語(yǔ)法:

  導(dǎo)入 :  require()
  導(dǎo)出:module.exports 或者 exports
    
2、AMD

環(huán)境:瀏覽器
特點(diǎn):(1)異步加載 (2)運(yùn)行時(shí)加載(3)管理依賴,依賴前置書寫 (4)依賴提前執(zhí)行(加載完立即執(zhí)行)
應(yīng)用:RequireJS
語(yǔ)法:

  導(dǎo)入:require(["依賴模塊"],fucntion(依賴模塊變量引用){回調(diào)函數(shù)})
  導(dǎo)出(定義):define(id?def?factory(){return ///})
3、CMD

環(huán)境:瀏覽器
特點(diǎn):(1)異步加載 (2)運(yùn)行時(shí)加載 (3)管理依賴,依賴就近書寫(4)依賴延遲執(zhí)行 (require的時(shí)候才執(zhí)行)
應(yīng)用:SeaJS
語(yǔ)法:

導(dǎo)入:require()
導(dǎo)出: define(function(require,exports,module){})
4、UMD

環(huán)境:瀏覽器或服務(wù)器
特點(diǎn):(1)兼容CommonJS AMD UMD 全局應(yīng)用
語(yǔ)法:無(wú)導(dǎo)入導(dǎo)出,只是一種兼容寫法

5、ES6 module

環(huán)境:瀏覽器或服務(wù)器
特點(diǎn):(1)編譯時(shí)加載(2)按需加載 (3)動(dòng)態(tài)更新
應(yīng)用:es6最新語(yǔ)法
語(yǔ)法:

導(dǎo)入 :import 
導(dǎo)出:export、 export default
各規(guī)范的區(qū)別提煉 1、CommonJS與ES6

1.1 是否動(dòng)態(tài)更新

es6 :輸出的值是動(dòng)態(tài)綁定,會(huì)實(shí)時(shí)動(dòng)態(tài)更新。
CommonJS :輸出的是值的緩存,不存在動(dòng)態(tài)更新

1.2 加載時(shí)機(jī)

//ES6模塊
import { basename, dirname, parse } from "path";
?
//CommonJS模塊
let { basename, dirname, parse } = require("path");

es6 :

編譯時(shí)加載,ES6可以在編譯時(shí)就完成模塊加載;
按需加載,ES6會(huì)從path模塊只加載3個(gè)方法,其他不會(huì)加載。
動(dòng)態(tài)引用,實(shí)時(shí)更新,當(dāng)ES6遇到import時(shí),不會(huì)像CommonJS一樣去執(zhí)行模塊,而是生成一個(gè)動(dòng)態(tài)的只讀引用,當(dāng)真正需要的時(shí)候再到模塊里去取值,所以ES6模塊是動(dòng)態(tài)引用,并且不會(huì)緩存值。

CommonJS:

運(yùn)行時(shí)加載
加載整個(gè)對(duì)象:require path模塊時(shí),其實(shí) CommonJS會(huì)將path模塊運(yùn)行一遍,并返回一個(gè)對(duì)象,并將這個(gè)對(duì)象緩存起來(lái),這個(gè)對(duì)象包含path這個(gè)模塊的所有API。
使用緩存值,不會(huì)實(shí)時(shí)更新:以后無(wú)論多少次加載這個(gè)模塊都是取第一次運(yùn)行的結(jié)果,除非手動(dòng)清除。因?yàn)镃ommonJS模塊輸出的是值的拷貝,所以當(dāng)模塊內(nèi)值變化時(shí),不會(huì)影響到輸出的值

2、CMD 與 AMD

2.1 cmd依賴就近,AMD依賴前置

// CMD
define(function(require, exports, module) {
    var a = require("./a")
    a.doSomething()       
    var b = require("./b") // 依賴可以就近書寫
    b.doSomething()
    // ... 
})
// AMD
define(["./a", "./b"], function(a, b) {// 依賴必須一開始就寫好
    a.doSomething()
    b.doSomething() 
    ...
})

2.2 CMD延遲執(zhí)行,AMD提前執(zhí)行

AMD

在加載模塊完成后就立即執(zhí)行該模塊,
當(dāng)所有模塊都加載執(zhí)行完成后 才會(huì)進(jìn)入require的回調(diào)函數(shù),執(zhí)行主邏輯
(會(huì)出現(xiàn) 那個(gè)依賴模塊先下載完,哪個(gè)就先執(zhí)行,與執(zhí)行順序書寫順序不一致
AMD RequireJS 從 2.0 開始,也改成可以延遲執(zhí)行(根據(jù)寫法不同,處理方式不同)

CMD

加載完某個(gè)依賴模塊后 并不執(zhí)行,
當(dāng)所有依賴模塊加載完成后進(jìn)入主邏輯,遇到require語(yǔ)句時(shí)才**執(zhí)行對(duì)應(yīng)依賴模塊**。
(保證了**執(zhí)行順序與書寫順序的一致**)




參考:

http://es6.ruanyifeng.com/#do...
https://zhuanlan.zhihu.com/p/...

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/97413.html

相關(guān)文章

  • 精讀《js 塊化發(fā)展》

    摘要:我是這一期的主持人黃子毅本期精讀的文章是。模塊化需要保證全局變量盡量干凈,目前為止的模塊化方案都沒(méi)有很好的做到這一點(diǎn)。精讀本次提出獨(dú)到觀點(diǎn)的同學(xué)有流形,黃子毅,蘇里約,,楊森,淡蒼,留影,精讀由此歸納。 這次是前端精讀期刊與大家第一次正式碰面,我們每周會(huì)精讀并分析若干篇精品好文,試圖討論出結(jié)論性觀點(diǎn)。沒(méi)錯(cuò),我們?cè)噲D通過(guò)觀點(diǎn)的碰撞,爭(zhēng)做無(wú)主觀精品好文的意見(jiàn)領(lǐng)袖。 我是這一期的主持人 ——...

    Freelander 評(píng)論0 收藏0
  • 前端工程化/構(gòu)建自動(dòng)化

    摘要:前端工程化的演化。前端較為流行的單元測(cè)試,等自動(dòng)化測(cè)試自動(dòng)化測(cè)試是軟件通過(guò)模擬瀏覽器,對(duì)頁(yè)面進(jìn)行操作,判斷是否產(chǎn)生預(yù)想的效果。 前端工程化 ??前端工程化的概念在近些年來(lái)逐漸成為主流構(gòu)建大型web應(yīng)用不可或缺的一部分,在此我通過(guò)以下這三方面總結(jié)一下自己的理解。 為什么需要前端工程化。 前端工程化的演化。 怎么實(shí)現(xiàn)前端工程化。 為什么需要工程化 ??隨著近些年來(lái)前端技術(shù)的不斷發(fā)展,越...

    JasonZhang 評(píng)論0 收藏0
  • 前端塊化雜談

    摘要:并不是使用安裝的模塊我們就可以使用同樣的方式使用任何一個(gè)模塊,使用某種工具將這些模塊打包發(fā)布作為事實(shí)上的前端模塊化標(biāo)準(zhǔn),或可以出來(lái)解救我們。目前比較拿的出手的,也就是的模塊化,比如或者等等,分別可以使用和。 Teambition是一家追求卓越技術(shù)的公司,我們工程師都很Geek,我們使用了很多新潮的,開源的技術(shù)。同時(shí)我們也貢獻(xiàn)了很多開源的項(xiàng)目。我們希望能夠把一些技術(shù)經(jīng)驗(yàn)分享給大家。...

    yacheng 評(píng)論0 收藏0
  • 前端塊化雜談

    摘要:并不是使用安裝的模塊我們就可以使用同樣的方式使用任何一個(gè)模塊,使用某種工具將這些模塊打包發(fā)布作為事實(shí)上的前端模塊化標(biāo)準(zhǔn),或可以出來(lái)解救我們。目前比較拿的出手的,也就是的模塊化,比如或者等等,分別可以使用和。 Teambition是一家追求卓越技術(shù)的公司,我們工程師都很Geek,我們使用了很多新潮的,開源的技術(shù)。同時(shí)我們也貢獻(xiàn)了很多開源的項(xiàng)目。我們希望能夠把一些技術(shù)經(jīng)驗(yàn)分享給大家。...

    li21 評(píng)論0 收藏0
  • 前端性能優(yōu)化(三)——傳統(tǒng) JavaScript 優(yōu)化的誤區(qū)

    摘要:二模塊化誤區(qū)加快加載和執(zhí)行的速度,一直是前端優(yōu)化的一個(gè)熱點(diǎn)。結(jié)果文件減少,也達(dá)到了預(yù)期的效果。避免不必要的延遲。最后再根據(jù)文件的功能類型,來(lái)決定是放在頁(yè)面的頭部還是尾部。 注:本文是純技術(shù)探討文,無(wú)圖無(wú)笑點(diǎn),希望您喜歡 一.前言 軟件行業(yè)極其缺乏前端人才這是圈內(nèi)的共識(shí)了,某種程度上講,同等水平前端的工資都要比后端高上不少,而圈內(nèi)的另一項(xiàng)共識(shí)則是——網(wǎng)頁(yè)是公司的臉面! 幾年前,谷歌的一項(xiàng)...

    UsherChen 評(píng)論0 收藏0
  • 前端資源系列(4)-前端學(xué)習(xí)資源分享&前端面試資源匯總

    摘要:特意對(duì)前端學(xué)習(xí)資源做一個(gè)匯總,方便自己學(xué)習(xí)查閱參考,和好友們共同進(jìn)步。 特意對(duì)前端學(xué)習(xí)資源做一個(gè)匯總,方便自己學(xué)習(xí)查閱參考,和好友們共同進(jìn)步。 本以為自己收藏的站點(diǎn)多,可以很快搞定,沒(méi)想到一入?yún)R總深似海。還有很多不足&遺漏的地方,歡迎補(bǔ)充。有錯(cuò)誤的地方,還請(qǐng)斧正... 托管: welcome to git,歡迎交流,感謝star 有好友反應(yīng)和斧正,會(huì)及時(shí)更新,平時(shí)業(yè)務(wù)工作時(shí)也會(huì)不定期更...

    princekin 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<