【函數(shù)表達(dá)式】閉包

定義函數(shù)的方法:Function類型

匿名函數(shù)——function關(guān)鍵字后面沒(méi)有標(biāo)識(shí)符的函數(shù)。
閉包——有權(quán)訪問(wèn)另一個(gè)函數(shù)作用域中的變量的函數(shù)。

//創(chuàng)建閉包的方法:在一個(gè)函數(shù)內(nèi)部創(chuàng)建另一個(gè)函數(shù)。
function createComparisonFunction(propertyName){
    return function (object1,object2) {
        var value1 = object1[propertyName];
        var value2 = object2[propertyName];
        if(value1<value2){
            return -1;
        }else if(value1>value2){
            return 1;
        }else{
            return 0;
        }
    }
}

一般來(lái)說(shuō),當(dāng)函數(shù)執(zhí)行完畢后,局部活動(dòng)對(duì)象就會(huì)被銷毀,內(nèi)存中僅保存全局作用于(全局執(zhí)行環(huán)境的變量對(duì)象)。但是,閉包的情況有所不同。

var compare = createComparisonFunction("name");
var result = compare({name:"Wonder"},{name:"Greg"});

上面代碼執(zhí)行時(shí),匿名函數(shù)從createComparisonFunction()中被返回后,它的作用域鏈被初始化為包含createComparisonFunction()函數(shù)的活動(dòng)對(duì)象和全局變量對(duì)象。這樣,匿名函數(shù)就可以訪問(wèn)在createComparisonFunction()中定義的所有變量。
更重要的是,createComparisonFunction()函數(shù)在執(zhí)行完畢后,其活動(dòng)對(duì)象也不會(huì)被銷毀,因?yàn)槟涿瘮?shù)的作用域鏈仍然在引用這個(gè)活動(dòng)對(duì)象。即當(dāng)createComparisonFunction()函數(shù)返回后,其執(zhí)行環(huán)境的作用域鏈會(huì)被銷毀,但它的活動(dòng)對(duì)象仍然會(huì)留在內(nèi)存中;直到匿名函數(shù)被銷毀后,createComparisonFunction()的活動(dòng)隊(duì)想才會(huì)被銷毀。

//創(chuàng)建函數(shù)
var compare = createComparisonFunction("name");  
//調(diào)用函數(shù)
var result = compare({name:"Wonder"},{name:"Greg"});
//接觸對(duì)匿名函數(shù)的引用(以便釋放內(nèi)存
compare = null;

由于閉包會(huì)攜帶包含它的函數(shù)的作用域,因此會(huì)比其他函數(shù)占用更多的內(nèi)存。過(guò)度使用閉包可能會(huì)導(dǎo)致內(nèi)存占用過(guò)多。

閉包與變量

閉包只能取得包含函數(shù)中任何變量的最后一個(gè)值。

function createFunctions() {
    var result = new Array();

    for (var i = 0; i < 10; i++) {
        result[i] = function () {
            return i;
        };
    }
    return result;
}
var re = createFunctions();
alert(re[0]());             //10

這個(gè)函數(shù)會(huì)返回一個(gè)函數(shù)數(shù)組。表面上看,似乎每個(gè)函數(shù)都應(yīng)該返回自己的索引值,但實(shí)際上,每個(gè)函數(shù)都返回10。因?yàn)槊總€(gè)函數(shù)的作用域鏈中都保存著createFunctions()函數(shù)的活動(dòng)對(duì)象,所以它們引用的都是同一個(gè)變量i。當(dāng)createFunctions()函數(shù)返回后,變量i的值是10,此時(shí)每個(gè)函數(shù)都引用這保存變量i的同一個(gè)變量對(duì)象,所以在每個(gè)函數(shù)內(nèi)部i的值都是10。

解決辦法:創(chuàng)建另一個(gè)匿名函數(shù)強(qiáng)制讓閉包的行為符合預(yù)期。

function createFunctions() {
    var result = new Array();

    for (var i = 0; i < 10; i++) {
        result[i] = function (num) {
            return function () {
                return num;
            };
        }(i);
    }
    return result;
}

var re = createFunctions();
alert(re[0]());

關(guān)于this對(duì)象

匿名函數(shù)的執(zhí)行環(huán)節(jié)具有全局性,因此this對(duì)象通常指向window。

var name = "window";
 var object = {
     name:"object",
     getNameFunc: function () {
         return function () {
             return this.name;
         }
     }
 }

 alert(object.getNameFunc()());  //(非嚴(yán)格模式下)window

每個(gè)函數(shù)在被調(diào)用時(shí)都會(huì)自動(dòng)取得兩個(gè)特殊變量:this和arguments。內(nèi)部函數(shù)在搜索這兩個(gè)變量時(shí),只會(huì)搜索到其活動(dòng)對(duì)象為止,因此永遠(yuǎn)不可能直接訪問(wèn)外部函數(shù)中的這兩個(gè)變量。
解決方案:把外部作用域中的this對(duì)象保存在一個(gè)閉包能夠訪問(wèn)到的變量里,就可以讓閉包訪問(wèn)該對(duì)象了。

var name = "window";
var object = {
    name:"object",
    getNameFunc: function () {
        var that = this;
        return function () {
            return that.name;
        }
    }
}

alert(object.getNameFunc()()); //object

內(nèi)存泄漏

IE9之前的版本對(duì)JScript對(duì)象和COM對(duì)象使用不同的垃圾回收例程,因此閉包在IE的這些版本中會(huì)導(dǎo)致一些特殊的問(wèn)題。

如果閉包的作用域鏈中保存著一個(gè)HTML元素,那么就意味著該元素將無(wú)法被銷毀。

function assignHandler(){
     var element = document.getElementById("someElement");
     element.onclick = function(){
         alert(element.id);
     }
 }

解決方案:

function assignHandler(){
    var element = document.getElementById("someElement");
    var id = element.id;
    element.onclick = function(){
        alert(id);
    }
    element = null;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 定義函數(shù)的方式有兩種:函數(shù)聲明和函數(shù)表達(dá)式。 函數(shù)聲明的一個(gè)重要特征就是函數(shù)聲明提升,意思是在執(zhí)行代碼前會(huì)先讀取函...
    oWSQo閱讀 737評(píng)論 0 0
  • 閉包 閉包是指有權(quán)訪問(wèn)另一個(gè)函數(shù)作用域中的變量的函數(shù)。創(chuàng)建閉包的常見(jiàn)方式就是在一個(gè)函數(shù)的內(nèi)部創(chuàng)建另一個(gè)函數(shù)。 當(dāng)某...
    胖胖冰閱讀 353評(píng)論 0 1
  • 函數(shù) 理解參數(shù) JavaScript函數(shù)不介意傳遞多少個(gè)參數(shù),也不介意傳遞參數(shù)的數(shù)據(jù)類型。也就是說(shuō)函數(shù)定義接受多少...
    TaoGeNet閱讀 268評(píng)論 0 2
  • 1? 為什么疲憊總是懶惰的最好借口,為什么輕松會(huì)成為快樂(lè)的理由?既然喜歡跋山涉水,為什么還要在意旅途的艱難? ...
    守望幸福_a029閱讀 372評(píng)論 0 2
  • THE NOW HABBIT 當(dāng)初高中的時(shí)候艾力老師推薦的書(shū),推薦了很多次,說(shuō)非常好非常好,于是抱著看一看也好的心...
    彭銘杰閱讀 914評(píng)論 0 3

友情鏈接更多精彩內(nèi)容