亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

再談JavaScript模塊化

MorePainMoreGain / 3597人閱讀

摘要:應(yīng)用日益復(fù)雜,模塊化已經(jīng)成為一個迫切需求。異步模塊加載機(jī)制。引用的資源列表太長,懶得回調(diào)函數(shù)中寫一一對應(yīng)的相關(guān)參數(shù)假定這里引用的資源有數(shù)十個,回調(diào)函數(shù)的參數(shù)必定非常多這就是傳說中的

簡述 緣起

模塊通常是指編程語言所提供的代碼組織機(jī)制,利用此機(jī)制可將程序拆解為獨立且通用的代碼單元。

模塊化主要是解決代碼分割、作用域隔離、模塊之間的依賴管理以及發(fā)布到生產(chǎn)環(huán)境時的自動化打包與處理等多個方面。

javascript應(yīng)用日益復(fù)雜,模塊化已經(jīng)成為一個迫切需求。但是作為一個模塊化方案,它至少要解決如下問題:

可維護(hù)性

避免作用域污染

代碼重用

依賴管理

script

最原始的方式就是,每個文件就是一個模塊,然后使用script的方式進(jìn)行引入。

但是此方式有以下問題:

全局作用域污染

無依賴管理,執(zhí)行順序依賴script標(biāo)簽的順序,如果采用異步加載,那會亂套,先下載的先執(zhí)行

IIFE 和 模塊對象

為了解決作用域污染的問題,就產(chǎn)生了立即執(zhí)行函數(shù) + 模塊對象模式:

// app1.js
var app = {};
// app2.js
(function(){
  app.a = function(a, b) {
    // code
  }  
})();
// app3.js
(function(app){
  var temp = [ 1, 2];
  var a = app.a(temp)
})(app);

具體的可以查閱阮一峰老師的博客Javascript模塊化編程(一):模塊的寫法

在ES6之前,js沒有塊級作用域,所以采用此方式建立一個函數(shù)作用域。但是在ES6之后,可以使用塊級作用域。

由于使用了IIFE,所以減少了全局作用域污染,但并不是徹底消除,因為還定義了一個appa模塊對象呢。

所以這也僅僅只是減少了作用域污染,還是會有其他缺點。

CommonJS

后來,有人試圖將javascript引入服務(wù)端,由于服務(wù)端編程相對比較復(fù)雜,就急需一種模塊化的方案,所以就誕生了commonjs,有require + module.exports實現(xiàn)模塊的加載和導(dǎo)出。

CommonJS采用同步的方式加載模塊,主要使用場景為服務(wù)端編程。因為服務(wù)器一般都是本地加載,速度較快。

AMD 和 CMD

后來,隨著前端業(yè)務(wù)的日漸復(fù)雜,瀏覽器端也需要模塊化,但是commonjs是同步加載的,這意味著加載模塊時,瀏覽器會凍結(jié),什么都干不了,這在瀏覽器肯定是不行的,這就誕生了AMD和CMD規(guī)范,分別以requirejs和seajs為代表。

這兩貨都采用異步方式加載模塊。

AMD

AMD(Asynchronous Module Defination)異步模塊加載機(jī)制。

define(
    [module_id,] // 模塊名字,如果缺省則為匿名模塊
    [dependenciesArray,] // 模塊依賴 
    definition function | object // 模塊內(nèi)容,可以為函數(shù)或者對象
);
CMD

CMD(Common Module Defination)通用模塊加載機(jī)制

// 方式一
define(function(require, exports, module) { 
    // 模塊代碼
    var a = require("a")
});
// 方式二
define( "module", ["module1", "module2"], function( require, exports, module ){
    // 模塊代碼
} );
區(qū)別

對于依賴的模塊,AMD 是提前執(zhí)行( RequireJS 從 2.0 開始,也改成可以延遲執(zhí)行),CMD 是延遲執(zhí)行

CMD 推崇依賴就近,AMD 推崇依賴前置

AMD 的 API 默認(rèn)是一個當(dāng)多個用,CMD 的 API 嚴(yán)格區(qū)分,推崇職責(zé)單一

不完美

盡管以上方案解決了上面說的問題,但是也帶來了一些新問題:

語法冗余,所有東西都要封裝在define中

AMD中的依賴列表必須與函數(shù)的參數(shù)列表匹配,易錯且修改苦難

Browserify

由于上述這些原因,有些人想在瀏覽器使用 CommonJS 規(guī)范,但 CommonJS 語法主要是針對服務(wù)端且是同步的,所以就產(chǎn)生了Browserify,它是一個 模塊打包器(module bundler),可以打包commonjs規(guī)范的模塊到瀏覽器中使用。

UMD

UMD(Universal Module Definition) 統(tǒng)一模塊定義。

AMD 與 CommonJS 雖然師出同源,但還是分道揚鑣,關(guān)注于代碼異步加載與最小化入口模塊的開發(fā)者將目光投注于 AMD;而隨著 Node.js 以及 Browserify 的流行,越來越多的開發(fā)者也接受了 CommonJS 規(guī)范。令人扼腕嘆息的是,符合 AMD 規(guī)范的模塊并不能直接運行于 CommonJS 模塊規(guī)范的環(huán)境中,符合 CommonJS 規(guī)范的模塊也不能由 AMD 進(jìn)行異步加載。

而且有這么多種規(guī)范,如果我們要發(fā)布一個模塊供其他人用,我們不可能為每種規(guī)范發(fā)布一個版本,就算你蛋疼這樣做了,別人使用的時候還得下載對應(yīng)版本,所以現(xiàn)在需要一種方案來兼容這些規(guī)范。

實現(xiàn)的方式就是在代碼前面做下判斷,根據(jù)不同的規(guī)范使用對應(yīng)的加載方式。

// 以vue為例
(function (global, factory) {
  typeof exports === "object" && typeof module !== "undefined" ? module.exports = factory() :
  typeof define === "function" && define.amd ? define(factory) :
  (global = global || self, global.Vue = factory());
}(this, function () { 
    // vue code ...
})

由于目前ES6瀏覽器支持還不夠好,所以很多第三方庫都采用了這種方式。

ESModule

ES6引入了ESModule規(guī)范,主要通過export + import來實現(xiàn),最終一統(tǒng)江湖??墒乾F(xiàn)實很骨感,一些瀏覽器并不支持(IE,說的就是你),所以還不能直接在瀏覽器中直接使用。

常用的兩種方案

在線編譯:requirejs/seajs/sytemjs

在頁面上加載一個AMD/CMD模塊格式解釋器。這樣瀏覽器就認(rèn)識了define, exports,module這些東西,也就實現(xiàn)了模塊化。

SystemJS 是一個通用的模塊加載器,它能在瀏覽器或者 NodeJS 上動態(tài)加載模塊,并且支持 CommonJS、AMD、全局模塊對象和 ES6 模塊。通過使用插件,它不僅可以加載 JavaScript,還可以加載 CoffeeScript 和 TypeScript。配合jspm也是不錯的搭配。

預(yù)編譯:browserify/webpack

相比于第一種方案,這個方案更加智能。由于是預(yù)編譯的,不需要在瀏覽器中加載解釋器。你在本地直接寫JS,不管是AMD/CMD/ES6風(fēng)格的模塊化,它都能認(rèn)識,并且編譯成瀏覽器認(rèn)識的JS。

注意: browerify只支持Commonjs模塊,如需兼容AMD模塊,則需要plugin轉(zhuǎn)換

CommonJS

前身為ServerJS。
我們可以理解為代碼會被如下內(nèi)建輔助函數(shù)包裹:

(function (exports, require, module, __filename, __dirname) {
    // ...
    // Your code
    // ...
});
加載

通過require加載模塊。

const a = require("a")
導(dǎo)出

通過exportsmodule.exports進(jìn)行模塊導(dǎo)出。

exportsexportsmodule.exports的一個引用,一個模塊可以使用多次,但是不能直接對exports重新賦值,只能通過如下方式使用

exports.a = function(){
    // code...
}

module.exports:一個模塊只能使用一次

module.exports = function(){
    // code...
}
特點

同步加載,定位于服務(wù)端,不適合瀏覽器

requirejs 特點

支持同步和異步兩種方式

大多數(shù)第三方庫都有兼容AMD,即時不兼容也可以通過配置使其可用

異步加載,不阻塞瀏覽器

依賴前置,可以很清楚看到當(dāng)前模塊的依賴

引入

在引入requirejs的script標(biāo)簽上添加data-main屬性定義入口文件,該文件會在requirejs加載完后立即執(zhí)行。

如果baseUrl未多帶帶配置,則默認(rèn)為引入require的文件的路徑。

config
requirejs.config({
    // 為模塊加上query參數(shù),解決瀏覽器緩存,只在開發(fā)環(huán)境使用
    urlArgs: "yn-course=" + (new Date()).getTime(),
    // 配置所有模塊加載的初始路徑,所有模塊都是基于此路徑加載
    baseUrl: "./", 
    // 映射一些快捷路徑,相當(dāng)于別名
    paths: {
        "~": "assets",
        "@": "components",
        "vue": "assets/lib/vue/vue",
        "vueRouter": "assets/lib/vue-router/vue-router",
        "jquery" : ["http://libs.baidu.com/jquery/2.0.3/jquery"]
    },
    //  對于匹配的模塊前綴,使用一個不同的模塊ID來加載該模塊
    map: {
        "layer": {
            "jquery": "http://libs.baidu.com/jquery/2.0.3/jquery"
        }
    },
    // 從CommonJS包(package)中加載模塊
    packages:{},
    // 加載上下文
    context:{},
    // 超時,默認(rèn)7S
    waitSeconds: 7,
    // 定義應(yīng)用依賴的模塊,在啟動后會加載此數(shù)組中的模塊
    deps: [],
    // 在deps加載完畢后執(zhí)行的函數(shù)
    callback:function(){},
    // 用來加載非AMD規(guī)范的模塊,以瀏覽器全局變量注入,此處僅作映射,需要在需要時手動載入
    shim: { 
        // "backbone": {
        //     deps: ["underscore", "jquery"], // 模塊依賴
        //     exports: "Backbone" // 導(dǎo)出的名稱
        // }
    },
    // 全局配置信息,可在模塊中通過module.config()訪問
    config:{
        color:"red"
    },
    // 如果設(shè)置為true,則當(dāng)一個腳本不是通過define()定義且不具備可供檢查的shim導(dǎo)出字串值時,就會拋出錯誤
    enforceDefine:false,
    // 如果設(shè)置為true,則使用document.createElementNS()去創(chuàng)建script元素
    xhtm: false,
    //指定RequireJS將script標(biāo)簽插入document時所用的type=""值
    scriptType:"text/javascript"
});

默認(rèn)requirejs會根據(jù)baseUrl+paths配置去查找模塊,但是如下情況例外:

路徑以.js結(jié)尾,比如lib/hello.js、hello.js

以“/”開始

包含url協(xié)議:如"http:"、"https"

設(shè)置baseURl的方式有如下三種:

requirejs.config指定;

如指data-main,則baseUrl為data-main所對應(yīng)的js的目錄

如果上述均未指定,則baseUrl為運行RequireJS的HTML文件所在目錄

map配置對于大型項目很重要:如有兩類模塊需要使用不同版本的"foo",但它們之間仍需要一定的協(xié)同。
在那些基于上下文的多版本實現(xiàn)中很難做到這一點。而且,paths配置僅用于為模塊ID設(shè)置root paths,而不是為了將一個模塊ID映射到另一個。

requirejs.config({
    map: {
        "some/newmodule": {
            "foo": "foo1.2"
        },
        "some/oldmodule": {
            "foo": "foo1.0"
        }
    }
});
define

通過define來定義模塊,推薦依賴前置原則,當(dāng)然也可以使用require動態(tài)按需加載。

define(
    [module_id,] // 模塊名字,如果缺省則為匿名模塊
    [dependencies,] // 模塊依賴 
    definition function | object // 模塊內(nèi)容,可以為函數(shù)或者對象
);
// 如果僅僅返回一個鍵值對,可以采用如下格式,類似JSONP
define({
    color: "black",
    size: "unisize"
})
//如果沒有依賴
define(function () {
    return {
        color: "black",
        size: "unisize"
    }
})
// 有依賴
define(["./a", "./b"], function(a, b) {
    
})
// 具名模塊
define("name",
    ["c", "d"],
    function(cart, inventory) {
    //此處定義foo/title object
    }   
)

如要在define()內(nèi)部使用諸如require("./a/b")相對路徑,記得將"require"本身作為一個依賴注入到模塊中:

define(["require", "./a/b"], function(require) {
    var mod = require("./a/b");
});

或者使用如下方式:

define(function(require) {
    var mod = require("./a/b");
})
標(biāo)識

require加載的所有模塊都是單例的,每個模塊都有一個唯一的標(biāo)識,這個標(biāo)識是模塊的名字或者模塊的相對路徑(如匿名模塊)。

模塊的唯一性與它們的訪問路徑無關(guān),即使是地址完全相同的一份JS文件,如果引用的方式與模塊的配置方式不一致,依舊會產(chǎn)生多個模塊。

// User.js
define([], function() {
    return {
        username : "yiifaa",
        age       : 20
    };
});
require(["user/User"], function(user) {
    //  修改了User模塊的內(nèi)容
    user.username = "yiifee";
    //  em/User以baseUrl定義的模塊進(jìn)行訪問
    //  "user/User"以path定義的模塊進(jìn)行訪問
    require(["em/User", "user/User"], function(u1, u2) {
        //  輸出的結(jié)果完全不相同,u1為yiifaa,u2為修改后的內(nèi)容yiifee
        console.log(u1, u2);
    })
})
依賴

requirejs推薦依賴前置,在define或者require模塊的時候,可以將需要依賴的模塊作為第一個參數(shù),以數(shù)組的方式聲明,然后在回調(diào)函數(shù)中,依賴會以參數(shù)的形式注入到該函數(shù)上,參數(shù)列表需要和依賴數(shù)組中位置一一對應(yīng)。

define(["./a", "./b"], function(a, b) {
    
})
導(dǎo)出

在requirejs中,有3中方式進(jìn)行模塊導(dǎo)出:

通過return方式導(dǎo)出,優(yōu)先級最高(推薦);

define(function(require, exports, module) {
    return {
        a : "a"
    }
});

通關(guān)module.exports對象賦值導(dǎo)出,優(yōu)先級次之;

define(function(require, exports, module) {
    module.exports = {
        a : "a"
    }
});

通過exports對象賦值導(dǎo)出,優(yōu)先級最低;

define(function(require, exports, module) {
    exports.a = "a"
});
require

requirejs提供了兩個全局變量requirerequirejs供我們加載模塊,這二者是完全等價的。

// 此處require 和 define 函數(shù)僅僅是一個參數(shù)(模塊標(biāo)識)的差異,
// 一般require用于沒有返回的模塊,如應(yīng)用頂層模塊
require(
    [dependencies,] // 模塊依賴 
    definition function // 模塊內(nèi)容
);

require是內(nèi)置模塊,不用在配置中定義,直接進(jìn)行引用即可。

define(["require"], function(require) {
    var $ = require("jquery");
})

requirejs支持異步(require([module]))和同步(require(module))兩種方式加載,即require參數(shù)為數(shù)組即為異步加載,反之為同步。

同步加載

在requirejs中,執(zhí)行同步加載必須滿足兩點要求:

必須在定義模塊時使用,亦即define函數(shù)中;

引用的資源必須是之前異步加載過的(不必在同一個模塊),換句話說,同步載入的模塊是不會發(fā)網(wǎng)絡(luò)請求的,只會調(diào)取之前緩存的模塊;

define(function(require, exports, module) { })中可以同步加載模塊

應(yīng)用場景

明確知道模塊的先后順序,確認(rèn)此模塊已經(jīng)被加載過,例如系統(tǒng)通用模塊,在載入完成后,之后的模塊就可以進(jìn)行同步的引用,或者在Vue等前端技術(shù)框架中,在應(yīng)用模塊同步加載vue模塊。

引用的資源列表太長,懶得回調(diào)函數(shù)中寫一一對應(yīng)的相關(guān)參數(shù)

//  假定這里引用的資源有數(shù)十個,回調(diào)函數(shù)的參數(shù)必定非常多
define(["jquery"], function() {
    return function(el) {
        //  這就是傳說中的同步調(diào)用
        var $ = require("jquery");
        $(el).html("Hello, World!");
    }
})

可以減少命名或者命名空間沖突,例如prototype與jquery的沖突問題

define(["jquery", "prototype"], function() {
    var export = {};
    export.jquery = function(el) {
        //  這就是傳說中的同步調(diào)用
        var $ = require("jquery");
        $(el).html("Hello, World!");
    }

    export.proto = function(el) {
        //  這就是傳說中的同步調(diào)用
        var $ = require("prototype");
        $(el).html("Hello, World!");
    }
    return export;
})

處女座專用,代碼顯得更整潔漂亮了,硬是把回調(diào)函數(shù)寫出了同步的感覺

異步加載

define([],function()):依賴數(shù)組中的模塊會異步加載,所有模塊加載完成后混執(zhí)行回調(diào)函數(shù)

require([]):傳入數(shù)組格式即表示需要異步加載

require === requirejs //=> true
require.toUrl("./a.css"): 獲取模塊url 模塊卸載

只要頁面不刷新,被requirejs加載的模塊只會執(zhí)行一次,后面會一直緩存在內(nèi)存中,即時重新引入模塊也不會再進(jìn)行初始化。
我們可以通過undef卸載已加載的模塊。

require.undef("moduleName") // moduleName是模塊標(biāo)識
其他 插件

css:加載css

text:加載HTML及其他文本

domReady

模塊加載錯誤

Module name has not been loaded yet for context: _

此錯誤表示執(zhí)行時模塊還未加載成功,一般為異步加載所致,改成同步加載即可。

借助類解決模塊間的相互干擾
//C模塊
define([],function(){
 
 // 定義一個類
 function DemoClass()
 {
    var count = 0;
    this.say = function(){
        count++;
        return count;
    };
 }
 
 return function(){
    //每次都返回一個新對象
    return new DemoClass();
 };
 
});
 
// A模塊
require(["C"],
  function(module) {
         cosole.log(module().say());//1
});
 
// B模塊
require(["C"],
  function(module) {
        cosole.log(module().say());//1
});

文檔:官方文檔,

[中文版](https://blog.csdn.net/wangzhanzheng/article/details/79050033)
seajs

Sea.js 追求簡單、自然的代碼書寫和組織方式,具有以下核心特性:

簡單友好的模塊定義規(guī)范:Sea.js 遵循 CMD 規(guī)范,可以像 Node.js 一般書寫模塊代碼。

自然直觀的代碼組織方式:依賴的自動加載、配置的簡潔清晰,可以讓我們更多地享受編碼的樂趣。

通過exports + require實現(xiàn)模塊的加載與導(dǎo)出。

引入


config
//seajs配置
seajs.config({

    //1.頂級標(biāo)識始終相對 base 基礎(chǔ)路徑解析。
    //2.絕對路徑和根路徑始終相對當(dāng)前頁面解析。
    //3.require 和 require.async 中的相對路徑相對當(dāng)前模塊路徑來解析。
    //4.seajs.use 中的相對路徑始終相對當(dāng)前頁面來解析。

    // Sea.js 的基礎(chǔ)路徑  在解析頂級標(biāo)識時,會相對 base 路徑來解析   base 的默認(rèn)值為 sea.js 的訪問路徑的父級
    base: "./",

    // 路徑配置  當(dāng)目錄比較深,或需要跨目錄調(diào)用模塊時,可以使用 paths 來簡化書寫
    paths: {
        gallery: "https://a.alipayobjects.com/gallery"
        /*
            var underscore = require("gallery/underscore");
            //=> 加載的是 https://a.alipayobjects.com/gallery/underscore.js
         */
    },

    // 別名配置  當(dāng)模塊標(biāo)識很長時,可以使用 alias 來簡化(相當(dāng)于 base 設(shè)置的目錄為基礎(chǔ))
    //Sea.js 在解析模塊標(biāo)識時, 除非在路徑中有問號(?)或最后一個字符是井號(#),否則都會自動添加 JS 擴(kuò)展名(.js)。如果不想自動添加擴(kuò)展名,可以在路徑末尾加上井號(#)。
    alias: {
        "seajs-css": "~/lib/seajs/plugins/seajs-css",
        "seajs-text": "~/lib/seajs/plugins/seajs-text",
        "$": "~/lib/zepto/zepto"
    },

    // 變量配置  有些場景下,模塊路徑在運行時才能確定,這時可以使用 vars 變量來配置
    vars: {
        //locale: "zh-cn"
        /*
            var lang = require("./i18n/{locale}.js");
            //=> 加載的是 path/to/i18n/zh-cn.js
         */
    },

    // 映射配置  該配置可對模塊路徑進(jìn)行映射修改,可用于路徑轉(zhuǎn)換、在線調(diào)試等
    map: [
        //[".js", "-debug.js"]
        /*
            var a = require("./a");
            //=> 加載的是 ./js/a-debug.js
        */
    ],

    // 預(yù)加載項  在普通模塊加載前,提前加載并初始化好指定模塊  preload 中的配置,需要等到 use 時才加載
    preload: ["seajs-css","seajs-text"],

    // 調(diào)試模式  值為 true 時,加載器不會刪除動態(tài)插入的 script 標(biāo)簽。插件也可以根據(jù) debug 配置,來決策 log 等信息的輸出
    debug: true,

    // 文件編碼  獲取模塊文件時, 一樣,會相對當(dāng)前頁面解析

use

用來在頁面中加載一個或多個模塊。seajs.use 理論上只用于加載啟動,不應(yīng)該出現(xiàn)在 define 中的模塊代碼里。在模塊代碼里需要異步加載其他模塊時,推薦使用 require.async 方法。

// 加載一個模塊
seajs.use("./a");

// 加載一個模塊,在加載完成時,執(zhí)行回調(diào)
seajs.use("./a", function(a) {
  a.doSomething();
});

// 加載多個模塊,在加載完成時,執(zhí)行回調(diào)
seajs.use(["./a", "./b"], function(a, b) {
  a.doSomething();
  b.doSomething();
});
define
// 方式一
define(function(require, exports, module) { 
    // 模塊代碼
    var a = require("a")
});
// 方式二,此方法嚴(yán)格來說不屬于CMD規(guī)范
define( "module", ["module1", "module2"], function( require, exports, module ){
    // 模塊代碼
});
// 如果模塊內(nèi)容僅是對象或者字符串
define({ "foo": "bar" });
define("I am a template. My name is {{name}}.");
require

require 是一個方法,接受 模塊標(biāo)識作為唯一參數(shù),用來獲取其他模塊提供的接口。

同步執(zhí)行

此方式,require 的參數(shù)值 必須 是字符串直接量。

var a = require("./a");
異步回調(diào)執(zhí)行

require.async 方法用來在模塊內(nèi)部異步加載模塊,并在加載完成后執(zhí)行指定回調(diào)。callback 參數(shù)可選。
此時,參數(shù)值可以是動態(tài)的,以實現(xiàn)動態(tài)加載。

define(function(require, exports, module) {

  // 異步加載一個模塊,在加載完成時,執(zhí)行回調(diào)
  require.async("./b", function(b) {
    b.doSomething();
  });

  // 異步加載多個模塊,在加載完成時,執(zhí)行回調(diào)
  require.async(["./c", "./d"], function(c, d) {
    c.doSomething();
    d.doSomething();
  });

});

require.resolve 使用模塊系統(tǒng)內(nèi)部的路徑解析機(jī)制來解析并返回模塊絕對路徑。

define(function(require, exports) {

  console.log(require.resolve("./b"));
  // ==> http://example.com/path/to/b.js

});
exports

exports 是一個對象,用來向外提供模塊接口,也可以使用return或者module.exports來進(jìn)行導(dǎo)出

define(function(require, exports) {

  // 對外提供 foo 屬性
  exports.foo = "bar";
  // return 
  return {
    foo: "bar",
    doSomething: function() {}
  };
  // module.exports
  module.exports = {
    foo: "bar",
    doSomething: function() {}
  };
});
module

module 是一個對象,上面存儲了與當(dāng)前模塊相關(guān)聯(lián)的一些屬性和方法。

module.id 模塊的唯一標(biāo)識

module.uri 根據(jù)模塊系統(tǒng)的路徑解析規(guī)則得到的模塊絕對路徑

module.dependencies 表示當(dāng)前模塊的依賴

module.exports 當(dāng)前模塊對外提供的接口

其他 插件

seajs-css

seajs-preload

seajs-text

seajs-style

seajs-combo

seajs-flush

seajs-debug

seajs-log

seajs-health

文檔:官方文檔

ESModule 簡介

在 ES6 之前,社區(qū)制定了一些模塊加載方案,最主要的有 CommonJS 和 AMD 兩種。前者用于服務(wù)器,后者用于瀏覽器。ES6 在語言標(biāo)準(zhǔn)的層面上,實現(xiàn)了模塊功能,而且實現(xiàn)得相當(dāng)簡單,完全可以取代 CommonJS 和 AMD 規(guī)范,成為瀏覽器和服務(wù)器通用的模塊解決方案。

嚴(yán)格模式

ES6 的模塊自動采用嚴(yán)格模式,不管你有沒有在模塊頭部加上"use strict";。

嚴(yán)格模式主要有以下限制:

變量必須聲明后再使用

函數(shù)的參數(shù)不能有同名屬性,否則報錯

不能使用with語句

不能對只讀屬性賦值,否則報錯

不能使用前綴 0 表示八進(jìn)制數(shù),否則報錯

不能刪除不可刪除的屬性,否則報錯

不能刪除變量delete prop,會報錯,只能刪除屬性delete global[prop]

eval不會在它的外層作用域引入變量

eval和arguments不能被重新賦值

arguments不會自動反映函數(shù)參數(shù)的變化

不能使用arguments.callee

不能使用arguments.caller

禁止this指向全局對象

不能使用fn.caller和fn.arguments獲取函數(shù)調(diào)用的堆棧

增加了保留字(比如protected、static和interface)

export 命令

定義模塊的對外接口。
一個模塊就是一個獨立的文件。該文件內(nèi)部的所有變量,外部無法獲取。如果你希望外部能夠讀取模塊內(nèi)部的某個變量,就必須使用export關(guān)鍵字輸出該變量。
以下是幾種用法:

//------輸出變量------
export var firstName = "Michael";
export var lastName = "Jackson";
//等價于
var firstName = "Michael";
export {firstName}; //推薦,能清除知道輸出了哪些變量
//------輸出函數(shù)或類------
export function multiply(x, y) {
  return x * y;
};
//------輸出并as重命名------
var v1 = "Michael";
function v2() { ... }
export {
  v1 as streamV1,
  v2 as streamV2
};
//------輸出default------
export default function () { ... }

注意:export default在一個模塊中只能有一個。

import 命令

使用export命令定義了模塊的對外接口以后,其他 JS 文件就可以通過import命令加載這個模塊。
以下是幾種用法,必須和上面的export對應(yīng):

//------加載變量、函數(shù)或類------
import {firstName, lastName} from "./profile.js";
//------加載并as重命名------
import { lastName as surname } from "./profile.js";
//------加載有default輸出的模塊------
import v1 from "./profile.js";
//------執(zhí)行所加載的模塊------
import "lodash";
//------加載模塊所有輸出------
import  * as surname from "./profile.js";
復(fù)合寫法

如果在一個模塊之中,先輸入后輸出同一個模塊,import語句可以與export語句寫在一起。

export { foo, bar } from "my_module";

// 等同于
import { foo, bar } from "my_module";
export { foo, bar };
不完美

只能出現(xiàn)在模塊頂層,不能在其他語句中

無法動態(tài)加載,其實這點主要是為了保證靜態(tài)分析,所有的模塊都要在解析階段確定它的依賴

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

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/105832.html

相關(guān)文章

  • 再談 JavaScript 異步編程

    摘要:隨著前端的發(fā)展,異步這個詞真是越來越常見了。真正帶來革命性改變的是規(guī)范。借助,我們可以這樣完成異步任務(wù)好棒寫起來像同步處理的函數(shù)一樣別著急,少年??偨Y(jié)以上就是筆者總結(jié)的幾種異步編程模式。 隨著前端的發(fā)展,異步這個詞真是越來越常見了。假設(shè)我們現(xiàn)在有這么一個異步任務(wù): 向服務(wù)器發(fā)起數(shù)次請求,每次請求的結(jié)果作為下次請求的參數(shù)。 來看看我們都有哪些處理方法: Callbacks ...

    RobinQu 評論0 收藏0
  • JS或Jquery

    摘要:大潮來襲前端開發(fā)能做些什么去年谷歌和火狐針對提出了的標(biāo)準(zhǔn),顧名思義,即的體驗方式,我們可以戴著頭顯享受沉浸式的網(wǎng)頁,新的標(biāo)準(zhǔn)讓我們可以使用語言來開發(fā)。 VR 大潮來襲 --- 前端開發(fā)能做些什么 去年谷歌和火狐針對 WebVR 提出了 WebVR API 的標(biāo)準(zhǔn),顧名思義,WebVR 即 web + VR 的體驗方式,我們可以戴著頭顯享受沉浸式的網(wǎng)頁,新的 API 標(biāo)準(zhǔn)讓我們可以使用 ...

    CatalpaFlat 評論0 收藏0
  • JavaScript設(shè)計模式(八):組合模式

    摘要:不同于其它靜態(tài)編程語言,實現(xiàn)組合模式的難點是保持樹對象與葉對象之間接口保持統(tǒng)一,可借助定制接口規(guī)范,實現(xiàn)類型約束。誤區(qū)規(guī)避組合不是繼承,樹葉對象并不是父子對象組合模式的樹型結(jié)構(gòu)是一種聚合的關(guān)系,而不是。 showImg(https://segmentfault.com/img/bVbu79V?w=800&h=600); 組合模式:又叫 部分整體 模式,將對象組合成樹形結(jié)構(gòu),以表示 部分...

    leon 評論0 收藏0
  • 再談閉包-詞法作用域

    摘要:權(quán)威指南第六版關(guān)于閉包的說明采用詞法作用域,也就是說函數(shù)的執(zhí)行依賴于變量的作用域,這個作用域是在函數(shù)定義時決定的,而不是函數(shù)調(diào)用時決定的。閉包這個術(shù)語的來源指函數(shù)變量可以被隱藏于作用域鏈之內(nèi),因此看起來是函數(shù)將變量包裹了起來。 最近打算換工作,所以參加了幾次面試(國內(nèi)比較知名的幾家互聯(lián)網(wǎng)公司)。在面試的過程中每當(dāng)被問起閉包,我都會說閉包是作用域的問題?令人驚訝的是幾乎無一例外的當(dāng)我提到...

    Ku_Andrew 評論0 收藏0
  • 再談Javascript原型繼承

    摘要:原型繼承基本模式這種是最簡單實現(xiàn)原型繼承的方法,直接把父類的對象賦值給子類構(gòu)造函數(shù)的原型,這樣子類的對象就可以訪問到父類以及父類構(gòu)造函數(shù)的中的屬性。 真正意義上來說Javascript并不是一門面向?qū)ο蟮恼Z言,沒有提供傳統(tǒng)的繼承方式,但是它提供了一種原型繼承的方式,利用自身提供的原型屬性來實現(xiàn)繼承。Javascript原型繼承是一個被說爛掉了的話題,但是自己對于這個問題一直沒有徹底理解...

    ThinkSNS 評論0 收藏0

發(fā)表評論

0條評論

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