摘要:為什么要使用模塊模式因為在全局作用域中聲明的變量和函數(shù)都自動成為全局對象的屬性,這經(jīng)常會導(dǎo)致命名沖突,還會導(dǎo)致一些非常重要的可維護(hù)性難題,全局變量越多,引入錯誤的概率就越大所以我們應(yīng)當(dāng)盡可能少地使用全局變量,模塊化的目的之一就是為了解決該問
為什么要使用模塊模式?
因為在全局作用域中聲明的變量和函數(shù)都自動成為全局對象Window的屬性,這經(jīng)常會導(dǎo)致命名沖突,還會導(dǎo)致一些非常重要的可維護(hù)性難題,全局變量越多,引入錯誤BUG的概率就越大!所以我們應(yīng)當(dāng)盡可能少地使用全局變量,模塊化的目的之一就是為了解決該問題的!
零全局變量模式該模式應(yīng)用場景較少,通過一個IIFE(立即執(zhí)行的匿名函數(shù)),將所有代碼包裝起來,這樣一來所有的變量、函數(shù)都被隱藏在該函數(shù)內(nèi)部,不會污染全局。
使用情景:
當(dāng)該代碼不會被其它代碼所依賴時;
當(dāng)不需要在運(yùn)行時不斷的擴(kuò)展或修改該代碼時;
當(dāng)代碼較短,且無需和其它代碼產(chǎn)生交互時;
單全局變量模式 基本定義單全局變量模式即只創(chuàng)建一個全局變量(或盡可能少地創(chuàng)建全局變量),且該全局變量的名稱必須是獨(dú)一無二的,不會和現(xiàn)在、將來的內(nèi)置API產(chǎn)生沖突,將所有的功能代碼都掛載到這個全局變量上。
它已經(jīng)被廣泛應(yīng)用于各種流行的類庫中,如:
YUI定義了唯一的YUI全局對象
JQuery定義了兩個全局對象,$和JQuery
Dojo定義了一個dojo全局對象
Closure定義了一個goog全局對象
例子:
var Mymodule= {}; Mymodule.Book = function(){...}; Mymodule.Book.prototype.getName = function(){....}; Mymodule.Car = function(){...}; Mymodule.Car.prototype.getWheels = function(){....};一個模塊的定義
模塊是一種通用的功能片段,它并沒有創(chuàng)建新的全局變量或命名空間,相反,所有的代碼都存放于一個單函數(shù)中,可以用一個名稱來表示這個模塊,同樣這個模塊可以依賴其他模塊。
function CoolModule(){ var something = "cool"; var another = [1,2,3]; function doSomething(){ console.log( something); } function doAnother(){ console.log(another.join("!")); } return { doSomething: doSomething, doAnother: doAnother }; } var foo = CoolModule(); foo.doSomething(); //cool foo.doAnother(); //1!2!3
這里的CoolModule 就是一個模塊,不過它只是一個函數(shù),這里調(diào)用CoolModule函數(shù)來創(chuàng)建一個模塊的實例foo,此時就形成了閉包(因為CoolModule返回一個對象,其中的一個屬性引用了內(nèi)部函數(shù)),模塊CoolModule返回的對象就是該模塊的公共API(也可以直接返回一個內(nèi)部函數(shù))
所以,模塊模式需要具備兩個必要條件:
必須有外部的封閉函數(shù),且該函數(shù)必須至少被調(diào)用一次(每次調(diào)用都會創(chuàng)建一個新的模塊實例),如CoolModule
封閉函數(shù)必須至少有一個內(nèi)部函數(shù)被返回,這樣內(nèi)部函數(shù)才能在私有作用域中形成閉包,并且可以訪問或修改私有的狀態(tài)
單例模塊模式的實現(xiàn):
var foo = ( function CoolModule(){ ...//代碼同上例 })(); foo.doSomething(); foo.doAnother();
還可以通過在模塊內(nèi)部保留對公共API對象的內(nèi)部引用,這樣就可以在內(nèi)部對模塊實例進(jìn)行修改,包括添加、刪除方法和屬性
function CoolModule(){ var something = "cool"; var another = [1,2,3]; function change() { pubicAPI.doSomething = doAnother; } function doSomething(){ console.log( something); } function doAnother(){ console.log(another.join("!")); } var pubicAPI = { change: change, doSomething: doSomething }; return pubicAPI; } var foo = CoolModule(); foo.doSomething(); //cool foo.change(); foo.doSomething(); //1!2!3 var foo1 = CoolModule(); foo1.doSomething(); //cool現(xiàn)代的模塊機(jī)制
命名空間是簡單的通過在全局變量中添加屬性來表示的功能性分組。
將不同功能按照命名空間進(jìn)行分組,可以讓你的單全局變量變得井然有序,同時可以讓團(tuán)隊成員能夠知曉新功能應(yīng)該在哪個部分中定義,或者去哪個部分查找已有功能。
例如:定義一個全局變量Y,Y.DOM下的所有方法都是和操作DOM相關(guān)的,Y.Event下的所有方法都是和事件相關(guān)的。
常見的用法是為每一個多帶帶的JS文件創(chuàng)建一個新的全局變量來聲明自己的命名空間;
每個文件都需要給一個命名空間掛載功能;這時就需要首先保證該命名空間是已經(jīng)存在的,可以在單全局變量中定義一個方法來處理該任務(wù):該方法在創(chuàng)建新的命名空間時不會對已有的命名空間造成破壞,使用命名空間時也不需要再去判斷它是否存在。
var MyGolbal = { namespace: function (ns) { var parts = ns.split("."), obj = this, i, len = parts.length; for(i=0;i大多數(shù)模塊依賴加載器或管理器,本質(zhì)上都是將這種模塊定義封裝進(jìn)一個友好的API
var MyModules = (function Manager() { var modules = {}; function define(name, deps, impl) { for(var i=0; i以上代碼的核心是modules[name] = impl.apply(impl,deps);,為了模塊的定義引入了包裝函數(shù)(可以傳入任何依賴),并且將模塊的API存儲在一個根據(jù)名字來管理的模塊列表modules對象中;
使用模塊管理器MyModules來管理模塊:MyModules.define("bar",[],function () { function hello(who) { return "let me introduce: "+who; } return{ hello: hello }; }); MyModules.define("foo",["bar"],function (bar) { var hungry = "hippo"; function awesome() { console.log(bar.hello(hungry).toUpperCase()); } return { awesome: awesome }; }); var foo = MyModules.get("foo"); foo.awesome();//LET ME INTRODUCE: HIPPO異步模塊定義(AMD):define("my-books", ["dependency1","dependency2"], function (dependency1, dependency2) { var Books = {}; Books.author = {author: "Mr.zakas"}; return Books; //返回公共接口API } );通過調(diào)用全局函數(shù)define(),并給它傳入模塊名字、依賴列表、一個工廠方法,依賴列表加載完成后執(zhí)行這個工廠方法。AMD模塊模式中,每一個依賴都會對應(yīng)到獨(dú)立的參數(shù)傳入到工廠方法里,即每個被命名的依賴最后都會創(chuàng)建一個對象被傳入到工廠方法內(nèi)。模塊可以是匿名的(即可以省略第一個參數(shù)),因為模塊加載器可以根據(jù)JavaScript文件名來當(dāng)做模塊名字。
要使用AMD模塊,需要通過使用與AMD模塊兼容的模塊加載器,如RequireJS、Dojo來加載AMD模塊requre(["my-books"] , function(books){ books.author; ... } )以上所說的模塊都是是基于函數(shù)的模塊,它并不是一個能被穩(wěn)定識別的模式(編譯器無法識別),它們的API語義只是在運(yùn)行時才會被考慮進(jìn)來。因此可以在運(yùn)行時修改一個模塊的API
未來的模塊機(jī)制ES6為模塊增加了一級語法支持,每個模塊都可以導(dǎo)入其它模塊或模塊的特定API成員,同樣也可以導(dǎo)出自己的API成員;ES6的模塊沒有‘行內(nèi)’格式,必須被定義在獨(dú)立的文件中(一個文件一個模塊)
ES6的模塊API更加穩(wěn)定,由于編譯器可以識別,在編譯時就檢查對導(dǎo)入的API成員的引用是否真實存在。若不存在,則編譯器會在運(yùn)行時就拋出‘早期’錯誤,而不會像往常一樣在運(yùn)行期采用動態(tài)的解決方案;bar.js
function hello(who) { return "let me introduce: "+who; } export hello; //導(dǎo)出API: hellofoo.js
//導(dǎo)入bar模塊的hello() import hello from "bar"; var hungry = "hippo"; function awesome() { console.log(hello(hungry).toUpperCase()); } export awesome;//導(dǎo)出API: awesomebaz.js
//完整導(dǎo)入foo和bar模塊 module foo from "foo"; module bar from "bar"; foo.awesome();import可以將一個模塊中的一個或多個API導(dǎo)入到當(dāng)前作用域中,并分別綁定在一個變量上;
module會將整個模塊的API導(dǎo)入并綁定到一個變量上;
export會將當(dāng)前模塊的一個標(biāo)識符(變量、函數(shù))導(dǎo)出為公共API;
模塊文件中的內(nèi)容會被當(dāng)做好像包含在作用域閉包中一樣來處理,就和函數(shù)閉包模塊一樣;
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/80552.html
摘要:執(zhí)行環(huán)境在很多方面都有其獨(dú)特之處全局變量和函數(shù)便是其中之一事實上的初始執(zhí)行環(huán)境是由多種多樣的全局變量所定義的這寫全局變量在腳本環(huán)境創(chuàng)建之初就已經(jīng)存在了我們說這些都是掛載在全局對象上的全局對象是一個神秘的對象它表示了腳本最外層上下文在瀏覽器中 JavaScript執(zhí)行環(huán)境在很多方面都有其獨(dú)特之處. 全局變量和函數(shù)便是其中之一. 事實上, js的初始執(zhí)行環(huán)境是由多種多樣的全局變量所定義的,...
摘要:既可以通過一個配置文件使用命令行接口來調(diào)用,也可以他自己的使用。使用最簡單的方法就是通過命令行接口。命令縮寫會以監(jiān)視模式運(yùn)行。這時運(yùn)行下將不會有錯誤拋出,包含導(dǎo)入的組件。 介紹 概覽 rollup是一個js打包器,用來將很細(xì)碎的js編譯打包成大的復(fù)雜的東西,像是一個庫或者一個應(yīng)用。其使用了ES6自帶的新標(biāo)準(zhǔn)來格式化和打包js代碼,而不是原先的Commonjs或者AMD這類解決方案。ES...
摘要:的模塊系統(tǒng)被設(shè)計成讓你可以一次性引入多個變量。動態(tài)靜態(tài),或者說規(guī)矩和如何打破規(guī)矩作為一門動態(tài)編程語言,令人驚訝地?fù)碛幸粋€靜態(tài)的模塊系統(tǒng)。只要你的需求都是靜態(tài)的話,這個模塊系統(tǒng)還是很的。 此文為翻譯,原文地址在這兒:https://hacks.mozilla.org/2015/08/es6-in-depth-modules/ ES6 是 ECMAScript 第 6 版本的簡稱,這是新一...
摘要:博客地址這篇文章是我在眾成翻譯翻譯的一篇文章,一篇的入門指南,原文鏈接的出現(xiàn)使得用寫服務(wù)端應(yīng)用成為可能。你可以看到,這個過程也安裝了其他的模塊,它們都是的所依賴的模塊。但是,得到的輸出信息會很冗長,我們可以加上來精簡一下輸出。 github 博客地址: https://github.com/zengxiaota... 這篇文章是我在 眾成翻譯 翻譯的一篇文章,一篇 npm 的入門指南,...
摘要:了解什么是官方文檔是這樣介紹的點我了解官方文檔簡單的來說,可以看做是模塊打包機(jī)它做的事情是,分析你的項目結(jié)構(gòu),找到模塊以及其它的一些瀏覽器不能直接運(yùn)行的拓展語言,等,并將其轉(zhuǎn)換和打包為合適的格式供瀏覽器使用。 了解webpack 什么是webpack 官方文檔是這樣介紹的:點我了解官方文檔 簡單的來說,WebPack可以看做是模塊打包機(jī):它做的事情是,分析你的項目結(jié)構(gòu),找到JavaSc...
閱讀 871·2021-11-24 09:38
閱讀 1098·2021-10-08 10:05
閱讀 2593·2021-09-10 11:21
閱讀 2809·2019-08-30 15:53
閱讀 1838·2019-08-30 15:52
閱讀 1979·2019-08-29 12:17
閱讀 3428·2019-08-29 11:21
閱讀 1619·2019-08-26 12:17