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

資訊專欄INFORMATION COLUMN

細說 Javascript 函數(shù)篇(三) : 閉包和引用

shevy / 3176人閱讀

Javascript 中一個最重要的特性就是閉包的使用。因為閉包的使用,當(dāng)前作用域總可以訪問外部的作用域。因為 Javascript 沒有塊級作用域,只有函數(shù)作用域,所以閉包的使用與函數(shù)是緊密相關(guān)的。

模擬私有變量
function Counter(start) {
    var count = start;
    return {
        increment: function() {
            count++;
        },

        get: function() {
            return count;
        }
    }
}

var foo = Counter(4);
foo.increment();
foo.get(); // 5

這里 Counter 返回兩個閉包:函數(shù) incrementget。這兩個函數(shù)一直保持著對 Counter 作用域的訪問,因此它們能一直訪問到定義在 Counter 作用域的變量 count。

私有變量的工作機制

由于 Javascript 不可以對作用域賦值和引用,所以在上例中,是沒有辦法在外部直接訪問內(nèi)部私有變量 count。唯一的方法就是通過定義閉包來訪問。

var foo = new Counter(4);
foo.hack = function() {
    count = 1337;
};

上面的代碼不會改變 Counter 作用域內(nèi)的 count 變量值,因為 hack 沒有在 Counter 內(nèi)定義。上面這段代碼只會創(chuàng)建或者覆蓋全局變量 count。

循環(huán)內(nèi)的閉包

一個最容易犯的錯誤就是在循環(huán)內(nèi)使用閉包。

for(var i = 0; i < 10; i++) {
    setTimeout(function() {
        console.log(i);  
    }, 1000);
}

上面這段代碼不會輸出0到9,而是連續(xù)輸出10次10。
上面的匿名會一直保持一個對變量 i 的引用。當(dāng)調(diào)用 console.log 函數(shù)開始輸出時,這是循環(huán)已經(jīng)結(jié)束,而變量 i 已經(jīng)為10了。
為了避免上面的錯誤發(fā)生,我們需要在每次循環(huán)時為變量 i 值創(chuàng)建一個拷貝。

避免引用錯誤

為了復(fù)制循環(huán)中變量的值,最好的方式是在外層加一個匿名的立刻執(zhí)行函數(shù)。

for(var i = 0; i < 10; i++) {
    (function(e) {
        setTimeout(function() {
            console.log(e);  
        }, 1000);
    })(i);
}

這個外部的匿名函數(shù)接收循環(huán)變量 i 作為第一個參數(shù),并將其值拷貝至它自身的參數(shù) e。
外部的匿名函數(shù)將參數(shù) e 再傳遞給 setTimeout,因此 setTimeout 有了指向參數(shù) e 的引用。而且這個參數(shù) e 的值不會因為外部的循環(huán)改變而改變。

  

這里涉及到了立即執(zhí)行函數(shù),它的具體含義可以參考這個回答:
http://segmentfault.com/q/1010000000442042#a-1020000000442404

還有另外一個方法可以實現(xiàn)同樣的效果,就是在 setTimeout 內(nèi)的匿名函數(shù)中再返回一個匿名函數(shù):

for(var i = 0; i < 10; i++) {
    setTimeout((function(e) {
        return function() {
            console.log(e);
        }
    })(i), 1000)
}

此外,通過 bind 方法也可以實現(xiàn)。

for(var i = 0; i < 10; i++) {
    setTimeout(console.log.bind(console, i), 1000);
}
參考

http://bonsaiden.github.io/JavaScript-Garden/#function.closures

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

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

相關(guān)文章

  • 細說 Javascript 函數(shù)(五) : ?構(gòu)造函數(shù)

    Javascript 中的構(gòu)造函數(shù)與其他語言相比也是不同的。任何通過關(guān)鍵字 new 調(diào)用的函數(shù)都可以當(dāng)做構(gòu)造函數(shù)。 在構(gòu)造函數(shù)體內(nèi),this 指向新創(chuàng)建的對象。如果構(gòu)造函數(shù)體內(nèi)沒有顯示的 return 表達式,那么我們就默認返回 this,也就是新建的對象。 function Foo() { this.bla = 1; } Foo.prototype.test = function()...

    sPeng 評論0 收藏0
  • 細說 Javascript 對象(二) : 原型對象

    摘要:并沒有類繼承模型,而是使用原型對象進行原型式繼承。我們舉例說明原型鏈查找機制當(dāng)訪問一個對象的屬性時,會從對象本身開始往上遍歷整個原型鏈,直到找到對應(yīng)屬性為止。原始類型有以下五種型。此外,試圖查找一個不存在屬性時將會遍歷整個原型鏈。 Javascript 并沒有類繼承模型,而是使用原型對象 prototype 進行原型式繼承。 盡管人們經(jīng)常將此看做是 Javascript 的一個缺點,然...

    lansheng228 評論0 收藏0
  • JavaScript:萬惡的 this 拿命來(

    摘要:閉包執(zhí)行上下文決定了變量作用域而閉包,它其實是一種決策,是一種模式,讓我們可以靈活的改變變量作用域。所以,在本質(zhì)上,閉包就是將函數(shù)內(nèi)部和函數(shù)外部連接起來的一座橋梁。只要咱們弄明白閉包,其中的自然跑不掉。 閉包 this 執(zhí)行上下文決定了變量作用域 而閉包,它其實是一種決策,是一種模式,讓我們可以靈活的改變變量作用域。 按慣例,上栗子 var global = glo...

    Cympros 評論0 收藏0
  • 細說 Javascript 類型) : instanceof 操作符

    摘要:的操作符可以用來比較兩個操作數(shù)的構(gòu)造函數(shù)。這是因為它們的構(gòu)造函數(shù)不可能會是同一個對象??偨Y(jié)綜上所述,我們知道操作符最合適的使用壞境是比較兩個相同上下文背景下的自定義對象的構(gòu)造函數(shù),正如上篇介紹的操作符,其他壞境下使用作用不大。 Javascript 的 instanceof 操作符可以用來比較兩個操作數(shù)的構(gòu)造函數(shù) constructor。但這個只有在比較自定義對象才有意義。當(dāng)用來比較 ...

    tylin 評論0 收藏0
  • 細說 jQuery 事件(一) - 代碼執(zhí)行時機

    摘要:在元素一篇介紹過,可以使用來使得代碼在加載完畢后自動執(zhí)行代碼,接下來具體介紹下這個機制。這樣看上去貌似沒什么問題,但是如果有兩個函數(shù)需要指定時就會遇到麻煩,因為屬性只能保存對一個函數(shù)的引用,如果我們寫成以下形式最后代碼執(zhí)行后的效果是會覆蓋。 在元素一篇介紹過,jQuery 可以使用 $(document).ready() 來使得代碼在 DOM 加載完畢后自動執(zhí)行代碼,接下來具體介紹下這...

    dunizb 評論0 收藏0

發(fā)表評論

0條評論

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