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

資訊專欄INFORMATION COLUMN

JavaScript 閉包

wwq0327 / 2203人閱讀

摘要:在文檔中,閉包的定義是。假設(shè)是一個(gè)被創(chuàng)建的局部變量是內(nèi)部函數(shù)一個(gè)閉包使用了父函數(shù)中聲明的變量通過(guò)以上的代碼塊來(lái)看,我們可以看到閉包實(shí)際上指的就是一個(gè)擁有外部環(huán)境變量的函數(shù)。

閉包

對(duì)于 JavaScript 的初學(xué)者來(lái)說(shuō),閉包的概念和應(yīng)用都可以算的上是難點(diǎn)。 MDN 的 JavaScript 文檔對(duì)閉包的概念給出了準(zhǔn)確的定義,也提供了簡(jiǎn)單直觀的的實(shí)例,是一個(gè)非常好的學(xué)習(xí)材料。 這篇文章將從文檔出發(fā),對(duì)閉包的知識(shí)點(diǎn)進(jìn)行一個(gè)簡(jiǎn)單的梳理。

閉包是什么

首先,我們需要對(duì)閉包提供一個(gè)準(zhǔn)確的定義。 在文檔中,閉包的定義是 "A closure is the combination of a function and the lexical environment within which that function was declared"。這個(gè)定義是很拗口的一句話。 詞法環(huán)境(lexical environment)這個(gè)描述對(duì)于初學(xué)者來(lái)說(shuō)過(guò)于學(xué)術(shù)和抽象,我們只需要記住就好。真正理解定義最好方式就是通過(guò)實(shí)際的代碼。 假設(shè):

function init() {
   var name = "Hello"; // name 是一個(gè)被 init 創(chuàng)建的局部變量
   function displayName() { 
       // displayName() 是內(nèi)部函數(shù),一個(gè)閉包
       alert(name); // 使用了父函數(shù)中聲明的變量
   }
   displayName(); 
}
init();

通過(guò)以上的代碼塊來(lái)看,我們可以看到閉包實(shí)際上指的就是一個(gè)’擁有外部環(huán)境變量的函數(shù)‘。 在上面的例子中函數(shù) displayName 調(diào)用了不屬于本身的外部變量 name,不管此 displayName 函數(shù)最終是否被返回,實(shí)際上由 name 和 displayName 組成的閉包已經(jīng)形成。

 function init() {
    var name = "Hello"; // name 是一個(gè)被 init 創(chuàng)建的局部變量
    function displayName() { 
        // displayName() 是內(nèi)部函數(shù),一個(gè)閉包
        alert(name); // 使用了父函數(shù)中聲明的變量
    }
    return displayName(); // 閉包被返回
}
var fun = init();
fun();

我們?cè)賮?lái)看一下這一塊的新的代碼,唯一的區(qū)別在于這個(gè)代碼中 函數(shù)init 返回了一個(gè)函數(shù) displayName()。也就是返回了一個(gè)閉包。通過(guò)這個(gè)返回的閉包,我們就可以訪問這個(gè)函數(shù)所相關(guān)聯(lián)的詞法環(huán)境或者說(shuō)數(shù)據(jù)。本來(lái)應(yīng)該被銷毀的 name 變量保留了下來(lái),而且只能通過(guò)調(diào)用閉包的方式來(lái)訪問,這也就是私有性。

閉包的作用

實(shí)際上在上一個(gè)例子中,我們已經(jīng)看到了閉包的作用,閉包可以用來(lái)模擬私有變量和方法。 它讓函數(shù)和函數(shù)所操作的某些數(shù)據(jù)(環(huán)境)關(guān)聯(lián)了起來(lái)。

var makeCounter = function() {
  var privateCounter = 0;
  function changeBy(val) {
    privateCounter += val;
  }
  return {
    increment: function() {
      changeBy(1);
    },
    decrement: function() {
      changeBy(-1);
    },
    value: function() {
      return privateCounter;
    }
  }  
};

var Counter1 = makeCounter();
var Counter2 = makeCounter();
console.log(Counter1.value()); /* logs 0 */
Counter1.increment();
Counter1.increment();
console.log(Counter1.value()); /* logs 2 */
Counter1.decrement();
console.log(Counter1.value()); /* logs 1 */
console.log(Counter2.value()); /* logs 0 */

在上面的例子中 我們可以看到變量 privateCounter 和 函數(shù) changeBy 作為下面三個(gè)函數(shù)共同的詞法環(huán)境形成了閉包。 在 makeCounter()執(zhí)行之后, 本該消失的詞法環(huán)境被保留下來(lái),只能通過(guò)返回的三個(gè)函數(shù)進(jìn)行更改和訪問。這種行為模擬出了類似 JAVA 類中的私有變量和私有方法。

在循環(huán)中創(chuàng)建閉包:一個(gè)常見錯(cuò)誤;

在 ECMAScript 2015 引入 let 這個(gè)關(guān)鍵字之前,在循環(huán)中有一個(gè)常見的閉包創(chuàng)建問題。

Helpful notes will appear here

E-mail:

Name:

Age:

function showHelp(help) {
  document.getElementById("help").innerHTML = help;
}

function setupHelp() {
  var helpText = [
      {"id": "email", "help": "Your e-mail address"},
      {"id": "name", "help": "Your full name"},
      {"id": "age", "help": "Your age (you must be over 16)"}
    ];

  for (var i = 0; i < helpText.length; i++) {
    var item = helpText[i];
    document.getElementById(item.id).onfocus = function() {
      showHelp(item.help);
    }
  }
}

setupHelp();

這段代碼的結(jié)果就是,無(wú)論你選擇哪一個(gè)輸入框,helper 信息永遠(yuǎn)都會(huì)顯示 Your age (you must be over 16)"。 原因就在于在返回的三個(gè)閉包實(shí)際上共享了 item 這一個(gè)詞法環(huán)境,所以 helper 永遠(yuǎn)只顯示為最后 age 的 helper。 這里就是閉包里另一個(gè)很重要的知識(shí)點(diǎn),閉包只會(huì)捕獲自由變量的引用,所以當(dāng) item 指向的helpText值最后變?yōu)?age 時(shí),三個(gè)閉包的中的 item 也都變成了 age。 根據(jù)這一點(diǎn)我們可以將代碼修改如下

function setupHelpAnonymous(){
    var helpText = [
      {"id": "email", "help": "Your e-mail address"},
      {"id": "name", "help": "Your full name"},
      {"id": "age", "help": "Your age (you must be over 16)"}
    ];

    for(var i = 0; i < helpText.length; i++){
      var item = helpText[i];
      (function() {
        var item = helpText[i];
        document.getElementById(item.id).onfocus = function() {
          showHelp(item.help);
        }
     })();
    }
  }

  setupHelpAnonymous()

在上面的代碼片段中 我們使用了一個(gè) IIFE (立即執(zhí)行函數(shù)表達(dá)式) 對(duì) item 這個(gè)引用進(jìn)行了立刻求值。這樣我們就能得到想要的結(jié)果。而在ES6中的 ’塊級(jí)作用域‘ 也可以解決這個(gè)問題。

function showHelp(help) {
  document.getElementById("help").innerHTML = help;
}

function setupHelp() {
  var helpText = [
      {"id": "email", "help": "Your e-mail address"},
      {"id": "name", "help": "Your full name"},
      {"id": "age", "help": "Your age (you must be over 16)"}
    ];

  for (var i = 0; i < helpText.length; i++) {
    let item = helpText[i];
    document.getElementById(item.id).onfocus = function() {
      showHelp(item.help);
    }
  }
}

setupHelp();

每一次循環(huán),都有一個(gè)新的 item 被創(chuàng)建,三個(gè)閉包不再共享同一個(gè)詞法環(huán)境;相比匿名閉包的方式,也沒有創(chuàng)建多余的閉包。

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

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

相關(guān)文章

  • Javascript閉包入門(譯文)

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

    Fourierr 評(píng)論0 收藏0
  • 理解Javascript閉包

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

    dayday_up 評(píng)論0 收藏0
  • JavaScript閉包,只學(xué)這篇就夠了

    摘要:當(dāng)在中調(diào)用匿名函數(shù)時(shí),它們用的都是同一個(gè)閉包,而且在這個(gè)閉包中使用了和的當(dāng)前值的值為因?yàn)檠h(huán)已經(jīng)結(jié)束,的值為。最好將閉包當(dāng)作是一個(gè)函數(shù)的入口創(chuàng)建的,而局部變量是被添加進(jìn)這個(gè)閉包的。 閉包不是魔法 這篇文章使用一些簡(jiǎn)單的代碼例子來(lái)解釋JavaScript閉包的概念,即使新手也可以輕松參透閉包的含義。 其實(shí)只要理解了核心概念,閉包并不是那么的難于理解。但是,網(wǎng)上充斥了太多學(xué)術(shù)性的文章,對(duì)于...

    CoderBear 評(píng)論0 收藏0
  • JavaScript深入之閉包

    摘要:深入系列第八篇,介紹理論上的閉包和實(shí)踐上的閉包,以及從作用域鏈的角度解析經(jīng)典的閉包題。定義對(duì)閉包的定義為閉包是指那些能夠訪問自由變量的函數(shù)。 JavaScript深入系列第八篇,介紹理論上的閉包和實(shí)踐上的閉包,以及從作用域鏈的角度解析經(jīng)典的閉包題。 定義 MDN 對(duì)閉包的定義為: 閉包是指那些能夠訪問自由變量的函數(shù)。 那什么是自由變量呢? 自由變量是指在函數(shù)中使用的,但既不是函數(shù)參數(shù)也...

    caige 評(píng)論0 收藏0
  • 還擔(dān)心面試官問閉包?

    摘要:一言以蔽之,閉包,你就得掌握。當(dāng)函數(shù)記住并訪問所在的詞法作用域,閉包就產(chǎn)生了。所以閉包才會(huì)得以實(shí)現(xiàn)。從技術(shù)上講,這就是閉包。執(zhí)行后,他的內(nèi)部作用域并不會(huì)消失,函數(shù)依然保持有作用域的閉包。 網(wǎng)上總結(jié)閉包的文章已經(jīng)爛大街了,不敢說(shuō)筆者這篇文章多么多么xxx,只是個(gè)人理解總結(jié)。各位看官瞅瞅就好,大神還希望多多指正。此篇文章總結(jié)與《JavaScript忍者秘籍》 《你不知道的JavaScri...

    tinyq 評(píng)論0 收藏0
  • [學(xué)習(xí)筆記] JavaScript 閉包

    摘要:但是,必須強(qiáng)調(diào),閉包是一個(gè)運(yùn)行期概念。通過(guò)原型鏈可以實(shí)現(xiàn)繼承,而與閉包相關(guān)的就是作用域鏈。常理來(lái)說(shuō),一個(gè)函數(shù)執(zhí)行完畢,其執(zhí)行環(huán)境的作用域鏈會(huì)被銷毀。所以此時(shí),的作用域鏈雖然銷毀了,但是其活動(dòng)對(duì)象仍在內(nèi)存中。 學(xué)習(xí)Javascript閉包(Closure)javascript的閉包JavaScript 閉包深入理解(closure)理解 Javascript 的閉包JavaScript ...

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

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

0條評(píng)論

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