成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

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

shevy / 3175人閱讀

Javascript 中一個(gè)最重要的特性就是閉包的使用。因?yàn)殚]包的使用,當(dāng)前作用域總可以訪問外部的作用域。因?yàn)?Javascript 沒有塊級(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 作用域的訪問,因此它們能一直訪問到定義在 Counter 作用域的變量 count。

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

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

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

上面的代碼不會(huì)改變 Counter 作用域內(nèi)的 count 變量值,因?yàn)?hack 沒有在 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ù)開始輸出時(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)
}

此外,通過 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://m.hztianpu.com/yun/87517.html

相關(guān)文章

  • 細(xì)說 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)建的對(duì)象。如果構(gòu)造函數(shù)體內(nèi)沒有顯示的 return 表達(dá)式,那么我們就默認(rèn)返回 this,也就是新建的對(duì)象。 function Foo() { this.bla = 1; } Foo.prototype.test = function()...

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

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

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

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

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

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

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

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

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

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

0條評(píng)論

shevy

|高級(jí)講師

TA的文章

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