国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

JS進(jìn)階篇--命名空間模式解析

warmcheng / 2818人閱讀

摘要:示例如下可以很容易的為對(duì)象字面量定義功能可以進(jìn)一步支撐對(duì)象命名空間與為對(duì)象添加屬性一樣,我們也可以直接將屬性添加到命名空間。對(duì)象字面量方法不會(huì)污染全局命名空間,并在邏輯上協(xié)助組織代碼和參數(shù)。

簡(jiǎn)介

在SF上看到這樣一個(gè)提問(wèn):
如題,因?yàn)椴坏靡训脑颍枰獙?xiě)若干個(gè)全局函數(shù)。但又不想這樣:

window.a = function(){}
window.b = function(){}
window.c = function(){}

題主問(wèn)有什么好的寫(xiě)法?
解答:
如果你用 jQuery,你可以這樣寫(xiě)

$.extend(window, {
    a: function() {},
    b: function() {},
    c: function() {}
});

如果你不用 jQuery,可以直接實(shí)現(xiàn)類似的 extend:

(() => {
    var defining = {
        a: function() { },
        b: function() { },
        c: function() { }
    };

    Object.keys(defining).forEach(key => {
        window[key] = defining[key];
    });
})();

在JavaScript中,命名空間可以幫助我們防止與全局命名空間下的其他對(duì)象或變量產(chǎn)生沖突。命名空間也有助于組織代碼,有更強(qiáng)的可維護(hù)性和可讀性。本文旨在探討JavaScript里的幾種常見(jiàn)命名空間模式,為我們提供一個(gè)思路。

一般命名空間的實(shí)現(xiàn)都以window為根。當(dāng)向window申請(qǐng)a.b.c的命名空間時(shí),首先在window中查看是否存在a這個(gè)成員,如果沒(méi)有則在 window下新建一個(gè)名為a的空關(guān)聯(lián)數(shù)組,如果已經(jīng)存在a,則繼續(xù)在window.a中查看b是否存在,以此類推。下面分別是Atlas和YUI中的實(shí)現(xiàn)方法。

Atlas命名空間的實(shí)現(xiàn)方法:

Function.registerNamespace =function(namespacePath){
    //以window為根
    var rootObject =window;
    //對(duì)命名空間路徑拆分成數(shù)組
    var namespaceParts =namespacePath.split(".");
    for (var i =0;i 

YUI命名空間的實(shí)現(xiàn)方法:

var YAHOO = window.YAHOO || {};
YAHOO.namespace = function(ns) {
    if (!ns || !ns.length) {
        return null;
    }
    var levels = ns.split(".");
    var nsobj = YAHOO;

    //如果申請(qǐng)的命名空間是在YAHOO下的,則必須忽略它,否則就成了YAHOO.YAHOO了
    for (var i=(levels[0] == "YAHOO") ? 1 : 0; i

YUI把所有申請(qǐng)的命名空間都放在了window.YAHOO下面,這樣有什么好處呢?假如Yahoo和其他公司有合作關(guān)系, 需要嵌入對(duì)方的腳本時(shí),這樣能保證它自己編寫(xiě)的代碼都在YAHOO這個(gè)空間下面,而其他公司不大可能在這個(gè)空間下面編碼,就基本不會(huì)出現(xiàn)命名沖突的情況。

我們一般的實(shí)現(xiàn)方式:

namespace = function(){
    var argus = arguments;
    for(var i = 0; i < argus.length; i++){
        var objs = argus[i].split(".");
        var obj = window;
        for(var j = 0; j < objs.length; j++){
            obj[objs[j]] = obj[objs[j]] || {};
            obj = obj[objs[j]];
        }
    }
    return obj;
};

namespace("tools.base");

當(dāng)然我們也常常利用js對(duì)象字面量的方式來(lái)實(shí)現(xiàn)js的命名空間:

var school = {
    addClass:function(classnum){
        console.log(classnum);
    },
    addStudent:function(stuId){
        console.log(stuId);
    }
}
school.addClass("2");

在全局作用域中聲明的任何變量和函數(shù)都是window對(duì)象的屬性,當(dāng)名稱有沖突時(shí),就會(huì)產(chǎn)生一些不可控的問(wèn)題。全局變量會(huì)帶來(lái)以下問(wèn)題:

命名沖突

代碼的脆弱性

難以測(cè)試

在編程開(kāi)發(fā)中合理的使用命名空間,可以避免相同的變量或?qū)ο竺Q產(chǎn)生的沖突。而且,命名空間也有助于組織代碼,有更強(qiáng)的可維護(hù)性和可讀性。JavaScript中雖然沒(méi)有提供原生的命名空間支持,但我們可以使用其他的方法(對(duì)象和閉包)實(shí)現(xiàn)類似的效果。下面就是一些常見(jiàn)的命名空間模式:

1.單一全局變量

JavaScript中一個(gè)流行的命名空間模式是選擇一個(gè)全局變量作為主要的引用對(duì)象。因?yàn)槊總€(gè)可能的全局變量都成為唯一全局變量的屬性,也就不用再創(chuàng)建多個(gè)全局變量,那么也就避免了和其他聲明的沖突。

單一全局變量模式已經(jīng)在不少的JavaScript類庫(kù)中使用,如:

YUI定義了唯一的YUI全局對(duì)象

jQuery定義了$和jQuery,$由其他類庫(kù)使用時(shí)使用jQuery

Dojo定義了一個(gè)Dojo全局變量

Closure類庫(kù)定義了一個(gè)goog全局對(duì)象

Underscore類庫(kù)定義了一個(gè)_ 全局對(duì)象

示例如下:

var myApplication = (function() {
    var count = 1;
     function funcur() {
        console.log(count);
     };
     return {
        funcur:funcur
     }
 })();
myApplication.funcur();

雖然單一全局變量模式適合某些情況,但其最大的挑戰(zhàn)是確保單一全局變量在頁(yè)面中是唯一使用的,不會(huì)發(fā)生命名沖突

2.命名空間前綴

命名空間前綴模式其思路非常清晰,就是選擇一個(gè)獨(dú)特的命名空間,然后在其后面聲明聲明變量、方法和對(duì)象。示例如下:

var  myApplication_propertyA = {};
var  myApplication_propertyB = {};

function myApplication_myMethod() {
    // ***
}

從某種程度上來(lái)說(shuō),它確實(shí)減少了命名沖突的發(fā)生概率,但其并沒(méi)有減少全局變量的數(shù)目。當(dāng)應(yīng)用程序規(guī)模擴(kuò)大時(shí),就會(huì)產(chǎn)生很多的全局變量。在全局命名空間內(nèi),這種模式對(duì)其他人都沒(méi)有使用的這個(gè)前綴有很強(qiáng)的依賴,而且有些時(shí)候也不好判斷是否有人已經(jīng)使用某個(gè)特殊前綴,在使用這種模式時(shí)一定要特別注意。

3.對(duì)象字面量表示法

對(duì)象字面量模式可以認(rèn)為是包含一組鍵值對(duì)的對(duì)象,每一對(duì)鍵和值由冒號(hào)分隔,鍵也可以是代碼新的命名空間。示例如下:

var myApplication = {
    // 可以很容易的為對(duì)象字面量定義功能
    getInfo:function() {
        // ***
    },
    
    // 可以進(jìn)一步支撐對(duì)象命名空間
    models:{},
    views:{
        pages:{}
    },
    collections:{}
};

與為對(duì)象添加屬性一樣,我們也可以直接將屬性添加到命名空間。對(duì)象字面量方法不會(huì)污染全局命名空間,并在邏輯上協(xié)助組織代碼和參數(shù)。并且,這種方式可讀性和可維護(hù)性非常強(qiáng),當(dāng)然我們?cè)谑褂脮r(shí)應(yīng)當(dāng)進(jìn)行同名變量的存在性測(cè)試,以此來(lái)避免沖突。下面是一些常用的檢測(cè)方法:

var myApplication = myApplication || {};

if(!myApplication) {
    myApplication  = {};
}

window.myApplication || (window.myApplication || {});

// 針對(duì)jQuery
var myApplication = $.fn.myApplication = function() {};

var myApplication = myApplication === undefined ? {} :myApplication;

對(duì)象字面量為我們提供了優(yōu)雅的鍵/值語(yǔ)法,我們可以非常便捷的組織代碼,封裝不同的邏輯或功能,而且可讀性、可維護(hù)性、可擴(kuò)展性極強(qiáng)。

4.嵌套命名空間

嵌套命名空間模式可以說(shuō)是對(duì)象字面量模式的升級(jí)版,它也是一種有效的避免沖突模式,因?yàn)榧词挂粋€(gè)命名空間存在,它也不太可能擁有同樣的嵌套子對(duì)象。示例如下:

var myApplication = myApplication || {};
 
 // 定義嵌套子對(duì)象
 myApplication.routers = myApplication.routers || {};
 myApplication.routers.test = myApplication.routers.test || {};

當(dāng)然,我們也可以選擇聲明新的嵌套命名空間或?qū)傩宰鳛樗饕龑傩裕纾?/p>

myApplication["routers"] = myApplication["routers"] || {};

使用嵌套命名空間模式,可以使代碼易讀且有組織性,而且相對(duì)安全,不易產(chǎn)生沖突。其弱點(diǎn)是,如果我們的命名空間嵌套過(guò)多,會(huì)增加瀏覽器的查詢工作量,我們可以把要多次訪問(wèn)的子對(duì)象進(jìn)行局部緩存,以此來(lái)減少查詢時(shí)間。

5.立即調(diào)用的函數(shù)表達(dá)式

立即調(diào)用函數(shù)(IIFE)實(shí)際上就是匿名函數(shù),被定義后立即被調(diào)用。在JavaScript中,由于變量和函數(shù)都是在這樣一個(gè)只能在內(nèi)部進(jìn)行訪問(wèn)的上下文中被顯式地定義,函數(shù)調(diào)用提供了一種實(shí)現(xiàn)私有變量和方法的便捷方式。IIFE是用于封裝應(yīng)用程序邏輯的常用方法,以保護(hù)它免受全局名稱空間的影響,其在命名空間方面也可以發(fā)揮其特殊的作用。示例如下:

;(function (namespace, undefined) {

    // 私有屬性
    var foo = "foo";
        bar = "bar";

    // 公有方法和屬性
    namespace.foobar = "foobar";
    namespace.sayHello = function () {
        say("Hello World!");
    };

    // 私有方法
    function say(str) {
        console.log("You said:" + str);
    };
})(window.namespace = window.namespace || {});

console.log(namespace.foobar); //foobar

可擴(kuò)展性是任何可伸縮命名空間模式的關(guān)鍵,使用IIFE可以輕松實(shí)現(xiàn)這一目的,我們可以再次使用IIFE給命名空間添加更多的功能。

6.命名空間注入

命名空間注入是IIFE的另一個(gè)變體,從函數(shù)包裝器內(nèi)部為一個(gè)特定的命名空間“注入”方法和屬性,使用this作為命名空間代理。這種模式的優(yōu)點(diǎn)是可以將功能行為應(yīng)用到多個(gè)對(duì)象或命名空間。示例如下:

var myApplication = myApplication || {};
myApplication.utils = {};

;(function () {
    var value = 5;
    
    this.getValue = function () {
        return value;
    }

    // 定義新的子命名空間
    this.tools = {};
}).apply(myApplication.utils);

(function () {
    this.diagnose = function () {
        return "diagnose";
    }
}).apply(myApplication.utils.tools);

// 同樣的方式在普通的IIFE上擴(kuò)展功能,僅僅將上下文作為參數(shù)傳遞并修改,而不是僅僅使用this

還有一種使用API來(lái)實(shí)現(xiàn)上下文和參數(shù)自然分離的方法,該模式感覺(jué)更像是一個(gè)模塊的創(chuàng)建者,但作為模塊,它還提供了一個(gè)封裝解決方案。示例如下:

var ns = ns || {},
    ns1 = ns1 || {};

// 模塊、命名空間創(chuàng)建者
var creator = function (val) {
    var val = val || 0;
    
    this.next = function () {
        return val ++ ;
    };

    this.reset = function () {
        val = 0;
    }
}

creator.call(ns);
// ns.next, ns.reset 此時(shí)已經(jīng)存在

creator.call(ns1, 5000);
// ns1包含相同的方法,但值被重寫(xiě)為5000了

console.log(ns.next()); //0
console.log(ns1.next());//5000

命名空間注入是用于為多個(gè)模塊或命名空間指定一個(gè)類似的功能基本集,但最好是在聲明私有變量或者方法時(shí)再使用它,其他時(shí)候使用嵌套命名空間已經(jīng)足以滿足需要了。

7.自動(dòng)嵌套的命名空間

嵌套命名空間模式可以為代碼單元提供有組織的結(jié)構(gòu)層級(jí),但每次創(chuàng)建一個(gè)層級(jí)時(shí),我們也得確保其有相應(yīng)的父層級(jí)。當(dāng)層級(jí)數(shù)量很大時(shí),會(huì)給我們帶來(lái)很大的麻煩,我們不能快速便捷的創(chuàng)建想創(chuàng)建的層級(jí)。那么如何解決這個(gè)問(wèn)題呢?Stoyan Stefanov提出,創(chuàng)建一個(gè)方法,其接收字符串參數(shù)作為一個(gè)嵌套,解析它,并自動(dòng)用所需的對(duì)象填充基本名稱空間。下面是這種模式的一種實(shí)現(xiàn):

function extend(ns, nsStr) {
    var parts = nsStr.split("."),
        parent = ns,
        pl;

    pl = parts.length;

    for (var i = 0; i < pl; i++) {
        // 屬性如果不存在,則創(chuàng)建它
        if (typeof parent[parts[i]] === "undefined") {
            parent[prats[i]] = {};
        }
        parent = parent[parts[i]];
    }
    return parent;
}

// 用法
var myApplication = myApplication || {};
var mod = extend(myApplication, "module.module2");

以前我們必須為其命名空間將各種嵌套顯式聲明為對(duì)象,現(xiàn)在用上述更簡(jiǎn)潔、優(yōu)雅的方式就實(shí)現(xiàn)了。

參考地址:JavaScript之命名空間模式 淺析

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/88935.html

相關(guān)文章

  • 2017-10-10 前端日?qǐng)?bào)

    摘要:前端日?qǐng)?bào)精選第期寫(xiě)給前端應(yīng)屆生的職業(yè)規(guī)劃建議應(yīng)用編譯優(yōu)化之路進(jìn)階篇命名空間模式解析源碼解析之任務(wù)管理入門(mén)教程快速上手聊聊改變歷史中文正式發(fā)布,帶來(lái)種新的圖表類型關(guān)系圖解好好寫(xiě)代碼吧使用手冊(cè)掘金發(fā)布在即將全面支持掘金仿懂球帝 2017-10-10 前端日?qǐng)?bào) 精選 【第1074期】寫(xiě)給前端應(yīng)屆生的職業(yè)規(guī)劃建議webpack 應(yīng)用編譯優(yōu)化之路JS進(jìn)階篇--命名空間模式解析gulp源碼解析之任...

    myshell 評(píng)論0 收藏0
  • 【連載】前端個(gè)人文章整理-從基礎(chǔ)到入門(mén)

    摘要:個(gè)人前端文章整理從最開(kāi)始萌生寫(xiě)文章的想法,到著手開(kāi)始寫(xiě),再到現(xiàn)在已經(jīng)一年的時(shí)間了,由于工作比較忙,更新緩慢,后面還是會(huì)繼更新,現(xiàn)將已經(jīng)寫(xiě)好的文章整理一個(gè)目錄,方便更多的小伙伴去學(xué)習(xí)。 showImg(https://segmentfault.com/img/remote/1460000017490740?w=1920&h=1080); 個(gè)人前端文章整理 從最開(kāi)始萌生寫(xiě)文章的想法,到著手...

    madthumb 評(píng)論0 收藏0
  • javascript知識(shí)點(diǎn)

    摘要:模塊化是隨著前端技術(shù)的發(fā)展,前端代碼爆炸式增長(zhǎng)后,工程化所采取的必然措施。目前模塊化的思想分為和。特別指出,事件不等同于異步,回調(diào)也不等同于異步。將會(huì)討論安全的類型檢測(cè)惰性載入函數(shù)凍結(jié)對(duì)象定時(shí)器等話題。 Vue.js 前后端同構(gòu)方案之準(zhǔn)備篇——代碼優(yōu)化 目前 Vue.js 的火爆不亞于當(dāng)初的 React,本人對(duì)寫(xiě)代碼有潔癖,代碼也是藝術(shù)。此篇是準(zhǔn)備篇,工欲善其事,必先利其器。我們先在代...

    Karrdy 評(píng)論0 收藏0
  • 正在暑假中的《課多周刊》(第1期)

    摘要:正在暑假中的課多周刊第期我們的微信公眾號(hào),更多精彩內(nèi)容皆在微信公眾號(hào),歡迎關(guān)注。若有幫助,請(qǐng)把課多周刊推薦給你的朋友,你的支持是我們最大的動(dòng)力。原理微信熱更新方案漲知識(shí)了,熱更新是以后的標(biāo)配。 正在暑假中的《課多周刊》(第1期) 我們的微信公眾號(hào):fed-talk,更多精彩內(nèi)容皆在微信公眾號(hào),歡迎關(guān)注。 若有幫助,請(qǐng)把 課多周刊 推薦給你的朋友,你的支持是我們最大的動(dòng)力。 遠(yuǎn)上寒山石徑...

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

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

0條評(píng)論

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