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

資訊專(zhuān)欄INFORMATION COLUMN

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

shevy / 3138人閱讀

Javascript 中一個(gè)最重要的特性就是閉包的使用。因?yàn)殚]包的使用,當(dāng)前作用域總可以訪問(wèn)外部的作用域。因?yàn)?Javascript 沒(méi)有塊級(jí)作用域,只有函數(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 返回兩個(gè)閉包:函數(shù) incrementget。這兩個(gè)函數(shù)一直保持著對(duì) Counter 作用域的訪問(wèn),因此它們能一直訪問(wèn)到定義在 Counter 作用域的變量 count。

私有變量的工作機(jī)制

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

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

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

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

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

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

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

避免引用錯(cuò)誤

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

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

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

  

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

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

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

此外,通過(guò) bind 方法也可以實(shí)現(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)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

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

相關(guān)文章

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

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

    sPeng 評(píng)論0 收藏0
  • 細(xì)說(shuō) Javascript 對(duì)象(二) : 原型對(duì)象

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

    lansheng228 評(píng)論0 收藏0
  • JavaScript:萬(wàn)惡的 this 拿命來(lái)(

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

    Cympros 評(píng)論0 收藏0
  • 細(xì)說(shuō) Javascript 類(lèi)型) : instanceof 操作符

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

    tylin 評(píng)論0 收藏0
  • 細(xì)說(shuō) jQuery 事件(一) - 代碼執(zhí)行時(shí)機(jī)

    摘要:在元素一篇介紹過(guò),可以使用來(lái)使得代碼在加載完畢后自動(dòng)執(zhí)行代碼,接下來(lái)具體介紹下這個(gè)機(jī)制。這樣看上去貌似沒(méi)什么問(wèn)題,但是如果有兩個(gè)函數(shù)需要指定時(shí)就會(huì)遇到麻煩,因?yàn)閷傩灾荒鼙4鎸?duì)一個(gè)函數(shù)的引用,如果我們寫(xiě)成以下形式最后代碼執(zhí)行后的效果是會(huì)覆蓋。 在元素一篇介紹過(guò),jQuery 可以使用 $(document).ready() 來(lái)使得代碼在 DOM 加載完畢后自動(dòng)執(zhí)行代碼,接下來(lái)具體介紹下這...

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

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

0條評(píng)論

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