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

資訊專欄INFORMATION COLUMN

JavaScript——閉包理解

AprilJ / 2302人閱讀

摘要:閉包占用大量內(nèi)存通常,函數(shù)的作用域及其所有的變量都會(huì)在函數(shù)執(zhí)行結(jié)束后被銷毀。也就是說,可以通過閉包創(chuàng)建私有作用域?qū)⒛承┳兞孔鳛榫植孔兞?,避免使用全局變量而占用過多的內(nèi)存。

JavaScript——閉包理解 1、閉包是什么,如何使用?

閉包指的是函數(shù)對象可以通過作用域鏈相互關(guān)聯(lián)起來,函數(shù)體內(nèi)部的變量都可以保存在函數(shù)作用域內(nèi),也就是說閉包有權(quán)訪問另一個(gè)函數(shù)作用域中的變量的函數(shù)。
下面是一個(gè)簡單閉包的函數(shù)

function mackFn() {
    var name = "Husky"
    function sayName () {
        console.log("name:" + name)
    }
    return sayName
}
var myFn = mackFn()
myFn()

mackFn()創(chuàng)建了一個(gè)局部變量name和一個(gè)名為sayName()的函數(shù)。sayName()是定義在mackFn()里的內(nèi)部函數(shù),sayName()可以訪問到外部函數(shù)的變量,所以sayName()可以使用父函數(shù)mackFn()函數(shù)中聲明的變量name。myFn是執(zhí)行了mackFn時(shí)創(chuàng)建的sayName函數(shù)實(shí)例的引用,且mackFn()函數(shù)形成閉包,所以sayName實(shí)例仍可訪問其詞法作用域的變量,即可以訪問name。

2、閉包的作用有哪些?
閉包其實(shí)用處很大,通過上面的例子,可以了解到閉包允許將數(shù)據(jù)與其所操作的某些數(shù)據(jù)關(guān)聯(lián)起來,因此但我們使用只有一個(gè)方法的對象的地方,就可以使用閉包。閉包可以用來訪問私有變量和模擬私有方法

通過閉包可以訪問私有變量的共有方法

閉包技術(shù)可以用來共享私有變量,下面的例子創(chuàng)建了一個(gè)addPrivateProperty()函數(shù)來實(shí)現(xiàn)私有屬性存取器方法。這個(gè)函數(shù)給對象o增加了屬性存取器方法,方法名稱為"get" + name"set" + name。如果提供了一個(gè)判定函數(shù), setter方法就會(huì)用它來檢測參數(shù)的合法性,然后再存儲(chǔ)它, 如果判定函數(shù)返回false,setter方法拋出異常。對于兩個(gè)存取器方法來說value這個(gè)變量是私有的,沒有辦法繞過存取器方法來設(shè)置或修改這個(gè)值。

function addPrivateProperty(o, name, predicate){
    var value   // 私有變量
    
    // 私有函數(shù)
    o["get" + name] = function() {
        return value
    }
    o["set" + name] = function(v) {
        if (predicate && !predicate(v)){
            throw Error("set" + name + ": invalid value" + v)
        } else {
            value = v
        }
    }
}

var o = {}   //設(shè)置一個(gè)空對象
addPrivateProperty(o, "Name",function(x){
    return typeof x == "string"
})
o.setName("Frank")  //設(shè)置屬性值
console.log(o.getName())   // => "Frank"

上述的例子中,在同一個(gè)作用域鏈中定義了兩個(gè)閉包,這兩個(gè)閉包共同享用同樣的私有變量或變量。

3、閉包存在的問題

閉包中的循環(huán)陷阱

通過循環(huán)創(chuàng)建多個(gè)閉包會(huì)產(chǎn)生一定的缺陷,即閉包只能取得包含函數(shù)中任何變量的最后一個(gè)值, 下面的第一個(gè)例子中,定時(shí)器函數(shù)返回的是10, 因?yàn)槊總€(gè)函數(shù)的作用域都保存著createFn()函數(shù)的活動(dòng)對象。所以它們引用的都是同一個(gè)變量n。當(dāng)createFn()函數(shù)中,執(zhí)行完循環(huán)之后變量n的值是10,此時(shí)每個(gè)定時(shí)器函數(shù)都應(yīng)用這保存變量n的同一個(gè)變量對象,所以在每個(gè)函數(shù)內(nèi)部n的值都是10

function createFn() {
  for (var n = 0; n < 5; n++) {
    setTimeout(function() {
      return console.log(n);
    }, 100 * n);
  }
}
createFn()   // => 5 5 5 5 5

可以通過定義了一個(gè)匿名函數(shù)并將立即執(zhí)行該匿名函數(shù),在調(diào)用每個(gè)匿名函數(shù)的時(shí)候,傳入了變量num,由于函數(shù)參數(shù)是按值傳遞的,所以就會(huì)將變量k的當(dāng)前值賦值給匿名函數(shù)的參數(shù)num,而在這個(gè)匿名函數(shù)的內(nèi)部,又會(huì)創(chuàng)建并返回了一個(gè)訪問k的閉包,因此定時(shí)器函數(shù)中都有自己k變量的一個(gè)副本,便可以返回不同的數(shù)值。

function createFn() {
  for (var k = 0; k < 10; k++) {
    (function(num) {
      setTimeout(function() {
        return console.log(num);
      }, 100 * k);
    })(k);
  }
}
createFn();  // => 1 2 3 4 5

閉包占用大量內(nèi)存

通常,函數(shù)的作用域及其所有的變量都會(huì)在函數(shù)執(zhí)行結(jié)束后被銷毀。但是,當(dāng)函數(shù)一旦返回了閉包,這個(gè)函數(shù)的作用域?qū)?huì)一直在內(nèi)存中保存到閉包不存在為止。
但是可以通過模仿塊級(jí)作用域來實(shí)現(xiàn)。通過創(chuàng)建并立即調(diào)用一個(gè)函數(shù),函數(shù)內(nèi)部的所有變量都會(huì)被立即銷毀(除某些變量賦值給了包含作用域中的變量),這樣既可以執(zhí)行其中的代碼,又不會(huì)在內(nèi)存中留在對該函數(shù)的引用。

function Fn(count) {
    (function() {
        for(var i = 0; i < count; i++) {
            console.log(i)
        }
    })()
    console.log("i:" + i)  // 拋出錯(cuò)誤
}
Fn(5)

通過創(chuàng)建函數(shù)Fn(),在for循環(huán)外部插入一個(gè)塊級(jí)作用域(私有作用域),在匿名函數(shù)中定義的任何變量,都會(huì)在執(zhí)行結(jié)束的時(shí)候被銷毀。因此,變量i只能坐在循環(huán)中使用,使用后就被銷毀。而在使用作用域中能夠訪問count變量,是因?yàn)檫@個(gè)匿名函數(shù)是一個(gè)閉包,它能夠訪問包含作用域中的所有變量。

4、性能優(yōu)化之內(nèi)存管理

通過創(chuàng)建私有作用域,在全局作用域中被函數(shù)外部使用,從而限制向全局作用域中添加過多的變量和函數(shù)。通過此方法不僅可以使用自己變量,而且不用擔(dān)心搞亂全局作用域。也就是說,可以通過閉包創(chuàng)建私有作用域?qū)⒛承┳兞孔鳛榫植孔兞?,避免使用全局變量而占用過多的內(nèi)存。

總結(jié)

閉包有著其優(yōu)點(diǎn),可以利用其優(yōu)點(diǎn)實(shí)現(xiàn)很多功能,如閉包可以用來訪問私有變量和模擬私有方法(訪問私有屬性的模式有很多,以后總結(jié))等等,但是因?yàn)閯?chuàng)建閉包必須維護(hù)額外的作用域,所以過渡使用閉包會(huì)占用大量的內(nèi)存。

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

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

相關(guān)文章

  • 理解 JavaScript 閉包

    摘要:如何在初學(xué)就理解閉包你需要接著讀下去。這樣定義閉包是函數(shù)和聲明該函數(shù)的詞法環(huán)境的組合。小結(jié)閉包在中隨處可見。閉包是中的精華部分,理解它需要具備一定的作用域執(zhí)行棧的知識(shí)。 這是本系列的第 4 篇文章。 作為 JS 初學(xué)者,第一次接觸閉包的概念是因?yàn)閷懗隽祟愃葡旅娴拇a: for (var i = 0; i < helpText.length; i++) { var item = he...

    寵來也 評論0 收藏0
  • 理解Javascript閉包

    摘要:但是閉包也不是什么復(fù)雜到不可理解的東西,簡而言之,閉包就是閉包就是函數(shù)的局部變量集合,只是這些局部變量在函數(shù)返回后會(huì)繼續(xù)存在??上У氖?,并沒有提供相關(guān)的成員和方法來訪問閉包中的局部變量。 (收藏自 技術(shù)狂) 前言:還是一篇入門文章。Javascript中有幾個(gè)非常重要的語言特性——對象、原型繼承、閉包。其中閉包 對于那些使用傳統(tǒng)靜態(tài)語言C/C++的程序員來說是一個(gè)新的語言特性。本文將...

    dayday_up 評論0 收藏0
  • Javascript閉包入門(譯文)

    摘要:也許最好的理解是閉包總是在進(jìn)入某個(gè)函數(shù)的時(shí)候被創(chuàng)建,而局部變量是被加入到這個(gè)閉包中。在函數(shù)內(nèi)部的函數(shù)的內(nèi)部聲明函數(shù)是可以的可以獲得不止一個(gè)層級(jí)的閉包。 前言 總括 :這篇文章使用有效的javascript代碼向程序員們解釋了閉包,大牛和功能型程序員請自行忽略。 譯者 :文章寫在2006年,可直到翻譯的21小時(shí)之前作者還在完善這篇文章,在Stackoverflow的How do Java...

    Fourierr 評論0 收藏0
  • 【譯】理解JavaScript閉包

    摘要:當(dāng)面試中讓我解釋一下閉包時(shí)我懵逼了。這個(gè)解釋開始可能有點(diǎn)晦澀,讓我們抽絲剝繭摘下閉包的真面目。此文不詳述作用域有專門的主題闡述,不過作用域是理解閉包原理的基礎(chǔ)。這才是閉包的真正便利之處。閉包使用不當(dāng)就會(huì)很坑。 原文鏈接 為什么深度學(xué)習(xí)JavaScript? JavaScript如今是最流行的編程語言之一。它運(yùn)行在瀏覽器、服務(wù)器、移動(dòng)設(shè)備、桌面應(yīng)用,也可能包括冰箱。無需我舉其他再多不相干...

    岳光 評論0 收藏0
  • 通過示例學(xué)習(xí)JavaScript閉包

    摘要:譯者按在上一篇博客,我們通過實(shí)現(xiàn)一個(gè)計(jì)數(shù)器,了解了如何使用閉包,這篇博客將提供一些代碼示例,幫助大家理解閉包。然而,如果通過代碼示例去理解閉包,則簡單很多。不過,將閉包簡單地看做局部變量,理解起來會(huì)更加簡單。 - 譯者按: 在上一篇博客,我們通過實(shí)現(xiàn)一個(gè)計(jì)數(shù)器,了解了如何使用閉包(Closure),這篇博客將提供一些代碼示例,幫助大家理解閉包。 原文: JavaScript Clos...

    xingpingz 評論0 收藏0
  • JavaScript中的閉包

    摘要:閉包引起的內(nèi)存泄漏總結(jié)從理論的角度將由于作用域鏈的特性中所有函數(shù)都是閉包但是從應(yīng)用的角度來說只有當(dāng)函數(shù)以返回值返回或者當(dāng)函數(shù)以參數(shù)形式使用或者當(dāng)函數(shù)中自由變量在函數(shù)外被引用時(shí)才能成為明確意義上的閉包。 文章同步到github js的閉包概念幾乎是任何面試官都會(huì)問的問題,最近把閉包這塊的概念梳理了一下,記錄成以下文章。 什么是閉包 我先列出一些官方及經(jīng)典書籍等書中給出的概念,這些概念雖然...

    HmyBmny 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<