成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

js中的模塊化——commonjs,AMD,CMD,UMD,ES6

qpal / 607人閱讀

摘要:若不存在則模塊標識應該默認定義為在加載器中被請求腳本的標識。這也是目前很多插件頭部的寫法,就是用來兼容各種不同模塊化的寫法。語句輸出的值是動態(tài)綁定的,綁定其所在的模塊。

前言

歷史上,js沒有模塊化的概念,不能把一個大工程分解成很多小模塊。這對于多人開發(fā)大型,復雜的項目形成了巨大的障礙,明顯降低了開發(fā)效率,java,Python有import,甚至連css都有@import,但是令人費解的是js居然沒有這方面的支持。es6出現(xiàn)之后才解決了這個問題,在這之前,各大社區(qū)也都出現(xiàn)了很多解決方法,比較出色的被大家廣為流傳的就有AMD,CMD,commonjs,UMD,今天我們就來分析這幾個模塊化的解決方案。

模塊加載

上面提到的幾種模塊化的方案的模塊加載有何異同呢?
先來說下es6模塊,es6模塊的設(shè)計思想是盡量靜態(tài)化,使得編譯時就能確定依賴關(guān)系,被稱為編譯時加載。其余的都只能在運行時確定依賴關(guān)系,這種被稱為運行時加載。下面來看下例子就明白了,比如下面這段代碼

let {a,b,c} = require("util");//會加載util里的所有方法,使用時只用到3個方法
import {a,b,c} from "util";//從util中加載3個方法,其余不加載
模塊化的幾種方案

下面簡單介紹一下AMD,CMD,commonjs,UMD這幾種模塊化方案。

commonjs

commonjs是服務(wù)端模塊化采用的規(guī)范,nodejs就采用了這個規(guī)范。
根據(jù)commonjs的規(guī)范,一個多帶帶的文件就是一個模塊,加載模塊使用require方法,該方法讀取文件并執(zhí)行,返回export對象。

// foobar.js
//私有變量
var test = 123;
//公有方法
function foobar () {
 
    this.foo = function () {
        // do someing ...
    }
    this.bar = function () {
        //do someing ...
    }
}
//exports對象上的方法和變量是公有的
var foobar = new foobar();
exports.foobar = foobar;
//讀取
var test = require("./foobar").foobar;
test.bar();

CommonJS 加載模塊是同步的,所以只有加載完成才能執(zhí)行后面的操作。像Node.js主要用于服務(wù)器的編程,加載的模塊文件一般都已經(jīng)存在本地硬盤,所以加載起來比較快,不用考慮異步加載的方式,所以CommonJS規(guī)范比較適用。但如果是瀏覽器環(huán)境,要從服務(wù)器加載模塊,這是就必須采用異步模式。所以就有了 AMD CMD 解決方案。

AMD

AMD是"Asynchronous Module Definition"的縮寫,意思就是"異步模塊定義"
AMD設(shè)計出一個簡潔的寫模塊API:

define(id?, dependencies?, factory);

第一個參數(shù) id 為字符串類型,表示了模塊標識,為可選參數(shù)。若不存在則模塊標識應該默認定義為在加載器中被請求腳本的標識。如果存在,那么模塊標識必須為頂層的或者一個絕對的標識。
第二個參數(shù),dependencies ,是一個當前模塊依賴的,已被模塊定義的模塊標識的數(shù)組字面量。
第三個參數(shù),factory,是一個需要進行實例化的函數(shù)或者一個對象。

看下下面的例子就明白了

define("alpha", [ "require", "exports", "beta" ], function( require, exports, beta ){
    export.verb = function(){
        return beta.verb();
        // or:
        return require("beta").verb();
    }
});

提到AMD就不得不提requirejs。
RequireJS 是一個前端的模塊化管理的工具庫,遵循AMD規(guī)范,它的作者就是AMD規(guī)范的創(chuàng)始人 James Burke。
AMD的基本思想就是先加載需要的模塊,然后返回一個新的函數(shù),所有的操作都在這個函數(shù)內(nèi)部操作,之前加載的模塊在這個函數(shù)里是可以調(diào)用的。

CMD

CMD是seajs在推廣的過程中對模塊的定義的規(guī)范化產(chǎn)出
和AMD提前執(zhí)行不同的是,CMD是延遲執(zhí)行,不過requirejs從2.0開始也開始支持延遲執(zhí)行了,這取決于寫法。
AMD推薦的是依賴前置,CMD推薦的是依賴就近。
看下AMD和CMD的代碼

//AMD
define(["./a","./b"], function (a, b) {
    //依賴一開始就寫好
    a.test();
    b.test();
});
 
//CMD
define(function (requie, exports, module) {
    //依賴可以就近書寫
    var a = require("./a");
    a.test();
    ...
    //軟依賴
    if (status) {
        var b = requie("./b");
        b.test();
    }
});
UMD

UMD是AMD和commonjs的結(jié)合
AMD適用瀏覽器,commonjs適用服務(wù)端,如果結(jié)合了兩者就達到了跨平臺的解決方案。
UMD先判斷是否支持AMD(define是否存在),存在用AMD模塊的方式加載模塊,再判斷是否支持nodejs的模塊(exports是否存在),存在用nodejs模塊的方式,否則掛在window上,當全局變量使用。
這也是目前很多插件頭部的寫法,就是用來兼容各種不同模塊化的寫法。

(function(window, factory) {
    //amd
    if (typeof define === "function" && define.amd) {
        define(factory);
    } else if (typeof exports === "object") { //umd
        module.exports = factory();
    } else {
        window.jeDate = factory();
    }
})(this, function() {  
...module..code...
})
ES6

es6的模塊自動采用嚴格模式,不管有沒有在頭部加上"use strict"
模塊是由export和import兩個命令構(gòu)成。

export命令

export命令可以出現(xiàn)在模塊的任何位置,只要處于模塊的頂層(不在塊級作用域內(nèi))即可。如果處于塊級作用域內(nèi),會報錯。

export語句輸出的值是動態(tài)綁定的,綁定其所在的模塊。

export default命令
//a.js
export default function(){
  console.log("aaa");
}
//b.js
import aaa from "a.js";

1.使用export default的時候,對應的import不需要使用大括號,import命令可以為default指定任意的名字。
2.不適用export default的時候,對應的import是需要使用大括號的
3.一個export default只能使用一次

import命令

import命令具有提升效果,會提升到整個模塊的頭部首先執(zhí)行,所以建議直接寫在頭部,這樣也方便查看和管理。

import語句會執(zhí)行所加載的模塊,因為有以下的寫法

  import "lodash;

上面的代碼僅僅執(zhí)行了lodash模塊,沒有輸入任何值

整體加載

整體加載有兩種方式

//import
import * as circle from "./circle"
//module
//module后面跟一個變量,表示輸入的模塊定義在該變量上
module circle from "./circle"
循環(huán)加載

在講循環(huán)加載前,先了解下commonjs和es6模塊加載的原理

commonjs模塊加載的原理

commonjs的一個模塊就是一個腳本文件,require命令第一次加載腳本的時候就會執(zhí)行整個腳本,然后在內(nèi)存中生成一個對象

{
  id:"...",
  exports: {...},
  loaded: true,
  ...
}

上面的對象中,id是模塊名,exports是模塊輸出的各個接口,loaded是一個布爾值,表示該模塊的腳本是否執(zhí)行完畢.
之后要用到這個模塊時,就會到exports上取值,即使再次執(zhí)行require命令,也不會執(zhí)行該模塊,而是到緩存中取值

es6模塊加載的

commonjs模塊輸入的是被輸出值的拷貝,也就是說一旦輸出一個值,模塊內(nèi)部的變化就影響不到這個值
es6的運行機制和commonjs不一樣,它遇到模塊加載命令import不會去執(zhí)行模塊,只會生成一個動態(tài)的只讀引用,等到真正要用的時候,再到模塊中去取值,由于es6輸入的模塊變量只是一個‘符號鏈接’,所以這個變量是只讀的,對他進行重新賦值會報錯。

import {obj} from "a.js";
obj.a = "qqq";//ok
obj = {}//typeError

分析完兩者的加載原理,來看下兩者的循環(huán)加載

commonjs的循環(huán)加載

commonjs模塊的重要特性是加載時執(zhí)行,即代碼在require的時候就會執(zhí)行,commonjs的做法是一旦出現(xiàn)循環(huán)加載,就只輸出已經(jīng)執(zhí)行的部分,還未執(zhí)行的部分不會輸出.
下面來看下commonjs中的循環(huán)加載的代碼

//a.js
exports.done = false;
var b = require("./b.js");
console.log("在a.js中,b.done=",b.done);
exports.done = true;
console.log("a.js執(zhí)行完畢")
//b.js
exports.done = false;
var a = require("./a.js");
console.log("在b.js中,a.done=",a.done);
exports.done = true;
console.log("b.js執(zhí)行完畢")
//main.js
var a = require("./a.js");
var b = require("./b.js");
console.log("在main.js中,a.done=",a.done,",b.done=",b.done);

上面的代碼中,執(zhí)行a.js的時候,a.js先輸出done變量,然后加載另一個腳本b.js,此時a的代碼就停在這里,等待b.js執(zhí)行完畢,再往下執(zhí)行。然后看下b.js的代碼,b.js也是先輸出done變量,然后加載a.js,這時發(fā)生了循環(huán)加載,按照commonjs的機制,系統(tǒng)會去a.js中的exports上取值,可是其實a.js是沒有執(zhí)行完的,只能輸出已經(jīng)執(zhí)行的部分done=false,然后b.js繼續(xù)執(zhí)行,執(zhí)行完畢后將執(zhí)行權(quán)返回給a.js,于是a.js繼續(xù)執(zhí)行,直到執(zhí)行完畢。
所以執(zhí)行main.js,結(jié)果為
在b.js中,a.done=false
b.js執(zhí)行完畢
在a.js中,b=done=true
a.js執(zhí)行完畢
在main.js中,a.done=true,b.done=true
上面這個例子說了兩點

在b.js中a.js沒有執(zhí)行完,只執(zhí)行了第一行

2.main.js中執(zhí)行到第二行不會再次執(zhí)行b.js,而是輸出緩存的b.js的執(zhí)行結(jié)果,即第4行

es6的循環(huán)加載

es6處理循環(huán)加載和commonjs不同,es6是動態(tài)引用,遇到模塊加載命令import時不會去執(zhí)行模塊,只會生成一個指向模塊的引用,需要開發(fā)者自己保證能取到輸出的值
看下面的例子

//a.js
import {odd} from "b.js";
export counter = 0;
export function even(n){
  counter++;
  return n==0 || odd(n-1);
}
//b.js
import {even} from "a.js";
export function odd(n){
  return n!=0 && even(n-1);
}
//main.js
import {event,counter } from "./a.js";
event(10)
counter //6

執(zhí)行main.js,按照commonjs的規(guī)范,上面的代碼是無法執(zhí)行的,因為a先加載b,b又加載a,但是a又沒有輸出值,b的even(n-1)會報錯
但是es6可以執(zhí)行,結(jié)果是6

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

轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/99618.html

相關(guān)文章

  • JS常見塊化規(guī)范(CommonJS/AMD/CMD/UMD/ES6 Module)

    摘要:常見模塊化方案是由社區(qū)提出的模塊化方案中的一種,遵循了這套方案。是模塊化規(guī)范中的一種,遵循了這套規(guī)范。中的模塊化能力由兩個命令構(gòu)成和,命令用于規(guī)定模塊的對外接口,命令用于輸入其他模塊提供的功能。 為什么需要模塊化 在ES6出現(xiàn)之前,JS語言本身并沒有提供模塊化能力,這為開發(fā)帶來了一些問題,其中最重要的兩個問題應當是全局污染和依賴管理混亂。 // file a.js var name =...

    walterrwu 評論0 收藏0
  • JS塊化——CommonJS AMD CMD UMD ES6 Module 比較

    摘要:即盡早地執(zhí)行依賴模塊。阮一峰輸出值的引用模塊是動態(tài)關(guān)聯(lián)模塊中的值,輸出的是值得引用。的加載實現(xiàn)阮一峰運行時加載靜態(tài)編譯模塊是運行時加載,模塊是編譯時輸出接口。 模塊化開發(fā) 優(yōu)點 模塊化開發(fā)中,通常一個文件就是一個模塊,有自己的作用域,只向外暴露特定的變量和函數(shù),并且可以按需加載。 依賴自動加載,按需加載。 提高代碼復用率,方便進行代碼的管理,使得代碼管理更加清晰、規(guī)范。 減少了命名沖...

    shadowbook 評論0 收藏0
  • JS模塊規(guī)范:AMDUMD、CMD、commonJS、ES6 module

    摘要:要想讓模塊再次運行,必須清除緩存。模塊加載會阻塞接下來代碼的執(zhí)行,需要等到模塊加載完成才能繼續(xù)執(zhí)行同步加載。環(huán)境服務(wù)器環(huán)境應用的模塊規(guī)范是參照實現(xiàn)的。這等同在每個模塊頭部,有一行這樣的命令。 commonJS 特點: 1、模塊可以多次加載,但是只會在第一次加載時運行一次,然后運行結(jié)果就被緩存了,以后再加載,就直接讀取緩存結(jié)果。要想讓模塊再次運行,必須清除緩存。2、模塊加載會阻塞接下來代...

    _ang 評論0 收藏0
  • JS基礎(chǔ)】一文看懂前端塊化規(guī)范

    摘要:參考資料前端模塊化詳解完整版入門近一萬字的語法知識點補充徹底搞清楚中的和和詳解 前言 前端的模塊化之路經(jīng)歷了漫長的過程,想詳細了解的小伙伴可以看浪里行舟大神寫的前端模塊化詳解(完整版),這里根據(jù)幾位大佬們寫的文章,將模塊化規(guī)范部分做了匯總和整理,希望讀完的小伙伴能有些收獲,也希望覺得有用的小伙伴可以點個贊,筆芯。 什么是模塊 將一個復雜的程序依據(jù)一定的規(guī)則(規(guī)范)封裝成幾個塊(文件)...

    HelKyle 評論0 收藏0
  • JS塊化編程

    摘要:也就是說,外部模塊輸出值變了,當前模塊的導入值不會發(fā)生變化。三規(guī)范的出現(xiàn),使得模塊化在環(huán)境中得到了施展機會。模塊化這種加載稱為編譯時加載或者靜態(tài)加載。總結(jié)的模塊化規(guī)范經(jīng)過了模塊模式的演進,利用現(xiàn)在常用的打包工具,非常方便我們編寫模塊化代碼。 前言 什么是模塊化? 模塊就是實現(xiàn)特定功能的一組方法,而模塊化是將模塊的代碼創(chuàng)造自己的作用域,只向外部暴露公開的方法和變量,而這些方法之間高度解耦...

    騫諱護 評論0 收藏0

發(fā)表評論

0條評論

qpal

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<