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

資訊專欄INFORMATION COLUMN

自調(diào)用匿名函數(shù)(匿名閉包)解析與調(diào)用

Scorpion / 640人閱讀

摘要:打開源碼,首先你會(huì)看到這樣的代碼結(jié)構(gòu)這是一個(gè)自調(diào)用匿名函數(shù)。模式,是自執(zhí)行函數(shù)的高級(jí)模式,可以非常方便的在各個(gè)匿名閉包中以全局對(duì)象調(diào)用閉包函數(shù)。

打開jQuery源碼,首先你會(huì)看到這樣的代碼結(jié)構(gòu):

(function(window,undefined ){

//

})();

這是一個(gè)自調(diào)用匿名函數(shù)。什么東東呢?在第一個(gè)括號(hào)內(nèi),創(chuàng)建一個(gè)匿名函數(shù);第二個(gè)括號(hào),立即執(zhí)行

為什么要?jiǎng)?chuàng)建這樣一個(gè)“自調(diào)用匿名函數(shù)”呢?
通過定義一個(gè)匿名函數(shù),創(chuàng)建了一個(gè)“私有”的命名空間,該命名空間的變量和方法,不會(huì)破壞全局的命名空間。這點(diǎn)非常有用也是一個(gè)JS框架必須支持的功能,jQuery被應(yīng)用在成千上萬(wàn)的JavaScript程序中,必須確保jQuery創(chuàng)建的變量不能和導(dǎo)入他的程序所使用的變量發(fā)生沖突。
接下來(lái)看看在 自調(diào)用匿名函數(shù) 中都實(shí)現(xiàn)了什么功能,按照代碼順序排列:

(function( window, undefined ) {

// 構(gòu)造jQuery對(duì)象
var jQuery = function( selector, context ) {
    return new jQuery.fn.init( selector, context, rootjQuery );
}
// 工具函數(shù) Utilities
// 異步隊(duì)列 Deferred
// 瀏覽器測(cè)試 Support
// 數(shù)據(jù)緩存 Data
// 隊(duì)列 queue
// 屬性操作 Attribute
// 事件處理 Event
// 選擇器 Sizzle
// DOM遍歷
// DOM操作
// CSS操作
// 異步請(qǐng)求 Ajax
// 動(dòng)畫 FX
// 坐標(biāo)和大小
window.jQuery = window.$ = jQuery;

})(window);

匿名函數(shù)從語(yǔ)法上叫函數(shù)直接量,JavaScript語(yǔ)法需要包圍匿名函數(shù)的括號(hào),事實(shí)上自調(diào)用匿名函數(shù)有兩種寫法:

(function() {

console.info( this );
console.info( arguments );

}( window ) );

(function() {

console.info( this );
console.info( arguments );

})( window );

為什么要傳入window呢?

通過傳入window變量,使得window由全局變量變?yōu)榫植孔兞浚?dāng)在jQuery代碼塊中訪問window時(shí),不需要將作用域鏈回退到頂層作用域,這樣可以更快的訪問window;這還不是關(guān)鍵所在,更重要的是,將window作為參數(shù)傳入,可以在壓縮代碼時(shí)進(jìn)行優(yōu)化,看看jquery-1.6.1.min.js: (function(a,b){})(window); // window 被優(yōu)化為 a
通過以上的介紹,我們大概了解通過()可以使得一個(gè)函數(shù)表達(dá)式立即執(zhí)行。

匿名函數(shù)作為一個(gè)“容器”,“容器”內(nèi)部可以訪問外部的變量,而外部環(huán)境不能訪問“容器”內(nèi)部的變量,
所以 ( function(){…} )() 內(nèi)部定義的變量不會(huì)和外部的變量發(fā)生沖突,俗稱“匿名包裹器”或“命名空間”。

(function () {

// ... 所有的變量和function都在這里聲明,并且作用域也只能在這個(gè)匿名閉包里
// ...但是這里的代碼依然可以訪問外部全局的對(duì)象

}());
同下面
(function () {/ 內(nèi)部代碼 /})();

通俗的講,()就是用來(lái)求值的,因此這個(gè)()任何時(shí)候都不能為空,因?yàn)樗且?jì)算的。函數(shù)解析它只會(huì)解析到 {}為止,不會(huì)解析到 ()的。

    把表達(dá)式放在()中會(huì)返回表達(dá)式的值;
    把函數(shù)放在()中會(huì)返回函數(shù)本身;(function(){}());
    如果()緊跟在函數(shù)后面,就是表示在調(diào)用函數(shù),即對(duì)函數(shù)求值:(function(){})();

(function() {

//自執(zhí)行函數(shù)中的內(nèi)部變量,外部是無(wú)法訪問的
var name = "kevin";

})( window );
name //undefined,無(wú)法獲取name的值

代碼在運(yùn)行過程中,會(huì)優(yōu)先解析 【巳聲明的函數(shù)】;

           而函數(shù)表達(dá)式是當(dāng)執(zhí)行到它時(shí),才會(huì)解析;
           匿名函數(shù)是不會(huì)多帶帶寫的,因此它的執(zhí)行是需要其它函數(shù)的調(diào)用,通??吹降哪涿瘮?shù),都是當(dāng)作參數(shù)被傳遞的。而立即執(zhí)行函數(shù)它本身就是個(gè)匿名函數(shù),
           js代碼執(zhí)行的順序:
            //巳聲明的函數(shù) function test(){}
            //匿名函數(shù)  function (){}
            //函數(shù)表達(dá)式 var test = function(){}
            //立即執(zhí)行函數(shù)  (function(){})();

立即執(zhí)行函數(shù)配合閉包,在模塊化中的應(yīng)用,其中要明白幾個(gè)點(diǎn):

1、要在函數(shù)體后面加括號(hào)就能立即調(diào)用,則這個(gè)函數(shù)必須是函數(shù)表達(dá)式,不能是函數(shù)聲明;
2、立即執(zhí)行函數(shù)可以當(dāng)作是一個(gè)私有作用域,作用域內(nèi)部可以訪問外部的變量,而外部環(huán)境是不能訪問作用域內(nèi)部的變量的,因此,立即執(zhí)行函數(shù)是一個(gè)封閉的作用域,不會(huì)和外部作用域起沖突。
   JQuery使用的就是這種方法,將JQuery代碼包裹在( function (window,undefined){…jquery代碼…} (window)中,在全局作用域中調(diào)用JQuery代碼時(shí),可以達(dá)到保護(hù)JQuery內(nèi)部變量的作用。
3、Module模式,是自執(zhí)行函數(shù)的高級(jí)模式,可以非常方便的在各個(gè)匿名閉包中以全局對(duì)象調(diào)用閉包函數(shù)。有興趣可以查看:http://www.cnblogs.com/TomXu/archive/2011/12/15/2288411.html                                Module 模式為:
   a.創(chuàng)建一個(gè)立即調(diào)用的匿名函數(shù)表達(dá)式
   b.return一個(gè)變量,其中這個(gè)變量里包含你要暴露的東西
      c.返回的這個(gè)變量將賦值給window

(function () {

var i = 0;
return {
    get: function () {
        return i;
    },
    set: function (val) {
        i = val;
    },
    increment: function () {
        return ++i;
    }
};

} (window));

    // window作為一個(gè)帶有多個(gè)屬性的全局對(duì)象,上面的代碼對(duì)于屬性的體現(xiàn)其實(shí)是方法,它可以這樣調(diào)用:
    window.get(); // 0
    window.set(3);
    window.increment(); // 4
    window.increment(); // 5

    window.i; // undefined 因?yàn)閕不是返回對(duì)象的屬性
    i; // 引用錯(cuò)誤: i 沒有定義(因?yàn)閕只存在于閉包)

/上面就是關(guān)于自調(diào)用匿名函數(shù)的解析,那么這樣的函數(shù)它是怎么被調(diào)用的呢?*/
/下面是關(guān)于全局變量的調(diào)用,也就是匿名閉包函數(shù)的調(diào)用*/

再次搬出Module模式,有興趣可以查看:http://www.cnblogs.com/TomXu/...
Module 模式,也就是匿名閉包的創(chuàng)建與調(diào)用:

   a.創(chuàng)建一個(gè)立即調(diào)用的匿名函數(shù)表達(dá)式
   b.return一個(gè)變量,其中這個(gè)變量里包含你要暴露的東西
      c.返回的這個(gè)變量將賦值給window

window(或者是任意一個(gè)全局對(duì)象)作為一個(gè)帶有多個(gè)屬性的全局對(duì)象,也可以把window當(dāng)成一個(gè)參數(shù),以對(duì)象的方式,在其它函數(shù)中實(shí)現(xiàn)調(diào)用。用下面的例子說(shuō)明:

(function ($, YAHOO) {

// 這里,我們的代碼就可以使用全局的jQuery對(duì)象了,YAHOO也是一樣
$.aa = function(){
    //code
}

} (jQuery, YAHOO));
//調(diào)用 jQuery.aa();

下面是一個(gè)標(biāo)準(zhǔn)的Module模式,通過匿名函數(shù)的返回值來(lái)返回這個(gè)全局變量:

var blogModule = (function () {

var my = {}, privateName = "博客園";

function privateAddTopic(data) {
    // 這里是內(nèi)部處理代碼
}

my.Name = privateName;
my.AddTopic = function (data) {
    privateAddTopic(data);
};

return my;

} ());
//調(diào)用 blogModule.my();

在一些大型項(xiàng)目里,將一個(gè)功能分離成多個(gè)文件是非常重要的,因?yàn)榭梢远嗳撕献饕子陂_發(fā)。再回頭看看上面的全局參數(shù)導(dǎo)入例子,我們能否把blogModule自身傳進(jìn)去呢?答案是肯定的,我們先將blogModule傳進(jìn)去,添加一個(gè)函數(shù)屬性,然后再返回就達(dá)到了我們所說(shuō)的目的:

var blogModule = (function (my) {

my.AddPhoto = function () {
    //添加內(nèi)部代碼  
};
return my;

} (blogModule || {}));

(function (my){

my.AddPhoto = function () {
    //添加內(nèi)部代碼  
};
return my;

})(blogModule || {}));
//調(diào)用 blogModule.AddPhoto();

那么,多個(gè)自執(zhí)行函數(shù)間是怎么調(diào)用的呢?

(function(owner) {

//第一個(gè)匿名閉包
owner.debug = true;
//Ajax相關(guān)參數(shù)配置
owner.ajax = {
    timeout: 10000,
    type: "post",
    dataType: "json",
};

})(window.C = {}));

如果第二個(gè)函數(shù)想調(diào)用 全局變量為C中的 對(duì)象呢?要怎么寫?

(function($, owner) {

//這里調(diào)用上面全局變量為C 中的對(duì)象呢
if(!C.debug) return false;
var url = "aaa.html";
mui.ajax({
    url: url,
    dataType: C.ajax.dataType,
    type: C.ajax.type,
});

})(mui, window.app = {});

再舉個(gè)例子,同樣的,不同自執(zhí)行閉包函數(shù)間的調(diào)用方法:

(function($, owner) {

//獲取語(yǔ)言閉包
owner.getLanguage = function() {
    var language = localStorage.getItem(C.state.field.language);
    if(typeof language == "undefined" || language === null || language == "") {
        var currentLang = navigator.language;
        if(!currentLang)
            currentLang = navigator.browserLanguage;
        language = currentLang.toLowerCase();
        language = language.replace(/-/g, "_");

        if(language != "en_us" && language != "zh_cn")
            language = "en_us";

        localStorage.setItem(C.state.field.language, language);
    }

    //在上面的解析中有說(shuō)過,Module模式,return 一個(gè)變量,這個(gè)變量就是要爆露的東西。通過這個(gè)函數(shù)的全局變量,這個(gè)  language  可以在任何地方調(diào)用   
    //return一個(gè)變量,其中這個(gè)變量里包含你要暴露的東西 
    //全局調(diào)用  storage.language                                  
    return language;
};

})(mui, window.storage = {}));

(function($, owner) {

owner.language = {};
owner.preload = function(settings){
    var defaults = {
        name: "i18n",
        language: "",
        path: "/",
        cache: true,
        encoding: "UTF-8",
        autoReplace: true,
        success: null,
        error: null,
    };
    
    settings = $.extend(defaults, settings);
    if(settings.language === null || settings.language == "") {
        //全局調(diào)用  storage.language                                                                            
        settings.language = storage.getLanguage();
    }
}                                        

})(mui, window.i18n = {});

所以 匿名閉包的調(diào)用規(guī)則是這樣的,立即執(zhí)行(最后一個(gè)括號(hào)) (window),如果把window作為一個(gè)參數(shù)進(jìn)行傳遞,那么就把它以對(duì)象的方式,在其它函數(shù)中實(shí)現(xiàn)全局調(diào)用。

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

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

相關(guān)文章

  • javascript基礎(chǔ)-函數(shù)

    摘要:在函數(shù)內(nèi)部定義的匿名函數(shù)的作用域鏈中,不包含外部函數(shù)的活動(dòng)對(duì)象。在執(zhí)行完畢以后,其執(zhí)行環(huán)境的作用域鏈被銷毀,但是其活動(dòng)對(duì)象不會(huì)被銷毀,因?yàn)槟涿瘮?shù)的作用域鏈中仍然引用著這個(gè)活動(dòng)對(duì)象,直到匿名函數(shù)執(zhí)行完畢后,才一起被銷毀。 函數(shù)表達(dá)式和函數(shù)聲明 函數(shù)聲明:function 函數(shù)名稱 (參數(shù):可選){ 函數(shù)體 } 函數(shù)表達(dá)式:function 函數(shù)名稱(可選)(參數(shù):可選){ 函數(shù)體 }...

    QLQ 評(píng)論0 收藏0
  • 深入理解JavaScript系列4:立即調(diào)用函數(shù)表達(dá)式

    摘要:前言大家學(xué)的時(shí)候,經(jīng)常遇到自執(zhí)行匿名函數(shù)的代碼,今天我們主要就來(lái)想想說(shuō)一下自執(zhí)行。其實(shí),前面兩個(gè)例子里的變量,也可以換成,因?yàn)楹屯饷娴牟辉谝粋€(gè)作用于,所以不會(huì)出現(xiàn)問題,這也是匿名函數(shù)閉包的威力。 前言 大家學(xué)JavaScript的時(shí)候,經(jīng)常遇到自執(zhí)行匿名函數(shù)的代碼,今天我們主要就來(lái)想想說(shuō)一下自執(zhí)行。 在詳細(xì)了解這個(gè)之前,我們來(lái)談了解一下自執(zhí)行這個(gè)叫法,本文對(duì)這個(gè)功能的叫法也不一定完全對(duì)...

    roadtogeek 評(píng)論0 收藏0
  • 深入理解JavaScript系列3:全面解析Module模式

    摘要:總結(jié)上面的大部分方式都可以互相組合使用的,一般來(lái)說(shuō)如果要設(shè)計(jì)系統(tǒng),可能會(huì)用到松耦合擴(kuò)展,私有狀態(tài)和子模塊這樣的方式。 簡(jiǎn)介 Module模式是JavaScript編程中一個(gè)非常通用的模式,一般情況下,大家都知道基本用法,本文嘗試著給大家更多該模式的高級(jí)使用方式。 首先我們來(lái)看看Module模式的基本特征: 模塊化,可重用 封裝了變量和function,和全局的namaspace不接觸...

    付倫 評(píng)論0 收藏0
  • 閉包的學(xué)習(xí)總結(jié)

    摘要:第一部分執(zhí)行代碼之后,返回了一個(gè)新的匿名函數(shù),此時(shí)在全局作用域調(diào)用匿名函數(shù)它不在是的屬性或者方法,此時(shí)調(diào)用者是因此輸出是??偨Y(jié)關(guān)于中的,記住誰(shuí)調(diào)用,就指向誰(shuí)要訪問閉包的,要定義個(gè)變量緩存下來(lái)。 前言: 這是一篇關(guān)于閉包函數(shù)的總結(jié)和筆記 希望對(duì)大家有點(diǎn)幫助 寫的不好的地方,也請(qǐng)大家多多指教 一: js中的命名函數(shù),匿名函數(shù),自調(diào)用函數(shù)和回調(diào)函數(shù) 1.命名函數(shù): 函數(shù)如果有名字,就...

    YanceyOfficial 評(píng)論0 收藏0
  • 進(jìn)擊的 JavaScript(五) 之 立即執(zhí)行函數(shù)閉包

    摘要:匿名函數(shù)是不能單獨(dú)寫的,所以就提不上立即執(zhí)行了。六立即執(zhí)行函數(shù)在閉包中的應(yīng)用立即執(zhí)行函數(shù)能配合閉包保存狀態(tài)。來(lái)看下上節(jié)內(nèi)容中閉包的例子現(xiàn)在,我們來(lái)利用立即執(zhí)行函數(shù)來(lái)簡(jiǎn)化它第一個(gè)匿名函數(shù)執(zhí)行完畢后,返回了第二個(gè)匿名函數(shù)。 前面的閉包中,提到與閉包相似的立即執(zhí)行函數(shù),感覺兩者還是比較容易弄混吧,嚴(yán)格來(lái)說(shuō)(因?yàn)橄透叱虒?duì)閉包的定義不同),立即執(zhí)行函數(shù)并不屬于閉包,它不滿足閉包的三個(gè)條件。...

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

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

0條評(píng)論

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