国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

JavaScript筆記——閉包

spacewander / 963人閱讀

摘要:閉包的問題使用閉包會(huì)將局部變量保持在內(nèi)存中,所以會(huì)占用大量內(nèi)存,影響性能。當(dāng)閉包的作用域中保存一些節(jié)點(diǎn)時(shí),較容易出現(xiàn)循環(huán)引用,可能會(huì)造成內(nèi)存泄漏。

前言

秋招大大小小若干場面試,幾乎都問了這個(gè)問題,當(dāng)然不知道閉包也不能說會(huì)js。所以,不要逃避,好好地來梳理一下。

閉包是什么?

來看看MDN官網(wǎng)上關(guān)于閉包的定義:

A closure is the combination of a function and the lexical environment within which that function was declared.

閉包是函數(shù)以及函數(shù)聲明所在的詞法環(huán)境的組合。這個(gè)定義有點(diǎn)干澀,個(gè)人認(rèn)為可以結(jié)合閉包的實(shí)際場景簡單地這么理解:函數(shù)調(diào)用結(jié)果返回一個(gè)子函數(shù),同時(shí)該子函數(shù)使用了外部函數(shù)的局部變量,使得變量保存在內(nèi)存中,形成了閉包。

舉個(gè)例子?

舉個(gè)最簡單的栗子~

function func(){
  var count = 0;
  return function(){
    console.log(count++);
  }
}

var fn = func();
fn(); // 0
fn(); // 1

func 函數(shù)執(zhí)行返回一個(gè)函數(shù),其中調(diào)用了func的局部變量count,導(dǎo)致func函數(shù)執(zhí)行完成后,count變量仍保留在內(nèi)存空間,未被銷毀,形成了閉包。

閉包的作用?

從上一個(gè)例子,可以看到閉包的特點(diǎn)是讀取函數(shù)內(nèi)部局部變量,并將局部變量保存在內(nèi)存,延長其生命周期。利用這個(gè)特點(diǎn)可以使用閉包實(shí)現(xiàn)以下功能:

解決類似循環(huán)綁定事件的問題
在實(shí)際開發(fā)中,經(jīng)常會(huì)遇到需要循環(huán)綁定事件的需求,比如上一篇博客的例子,在id為container的元素中添加5個(gè)按鈕,每個(gè)按鈕的文案是相應(yīng)序號,點(diǎn)擊打印輸出對應(yīng)序號。
其中第一個(gè)方法很容易錯(cuò)誤寫成:

var container = document.getElementById("container");
for(var i = 1; i <= 5; i++) {
 var btn = document.createElement("button"),
     text = document.createTextNode(i);
 btn.appendChild(text);
 btn.addEventListener("click", function(){
   console.log(i);
 })
 container.appendChild(btn);
}

雖然給不同的按鈕分別綁定了事件函數(shù),但是5個(gè)函數(shù)其實(shí)共享了一個(gè)變量 i。由于點(diǎn)擊事件在 js 代碼執(zhí)行完成之后發(fā)生,此時(shí)的變量 i 值為6,所以每個(gè)按鈕點(diǎn)擊打印輸出都是6。
為了解決這個(gè)問題,我們可以修改代碼,給各個(gè)點(diǎn)擊事件函數(shù)建立獨(dú)立的閉包,保持不同狀態(tài)的i。

var container = document.getElementById("container");
for(var i = 1; i <= 5; i++) {
 (function(_i) {
   var btn = document.createElement("button"),
       text = document.createTextNode(_i);
   btn.appendChild(text);
   btn.addEventListener("click", function(){
     console.log(_i);
   })
   container.appendChild(btn);
 })(i);
}

注:解決這個(gè)問題更好的方法是使用 ES6 的 let,聲明塊級的局部變量。

封裝私有變量

經(jīng)典的計(jì)數(shù)器例子:

function makeCounter() {
  var value = 0;
  return {
    getValue: function() {
      return value;
    },
    increment: function() {
      value++;
    },
    decrement: function() {
      value--;
    }
  }
}

var a = makeCounter();
var b = makeCounter();
b.increment();
b.increment();
b.decrement();
b.getValue(); // 1
a.getValue(); // 0
a.value; // undefined

每次調(diào)用makeCounter函數(shù),環(huán)境是不相同的,所以對b進(jìn)行的increment/decrement操作不會(huì)影響a的value屬性。同時(shí),對value屬性,只能通過getValue方法進(jìn)行訪問,而不能直接通過value屬性進(jìn)行訪問。

閉包的問題?

使用閉包會(huì)將局部變量保持在內(nèi)存中,所以會(huì)占用大量內(nèi)存,影響性能。所以在不再需要使用這些局部變量的時(shí)候,應(yīng)該手動(dòng)將這些變量設(shè)置為null, 使變量能被回收。

當(dāng)閉包的作用域中保存一些DOM節(jié)點(diǎn)時(shí),較容易出現(xiàn)循環(huán)引用,可能會(huì)造成內(nèi)存泄漏。原因是在IE9以下的瀏覽器中,由于BOM 和DOM中的對象是使用C++以COM 對象的方式實(shí)現(xiàn)的,而COM對象的垃圾收集機(jī)制采用的是引用計(jì)數(shù)策略,當(dāng)出現(xiàn)循環(huán)引用時(shí),會(huì)導(dǎo)致對象無法被回收。當(dāng)然,同樣可以通過設(shè)置變量為null解決。

舉例如下:

function func() {
  var element = document.getElementById("test");
  element.onClick = function() {
      console.log(element.id);
  };
}

func 函數(shù)為 element 添加了閉包點(diǎn)擊事件,匿名函數(shù)中又對element進(jìn)行了引用,使得 element 的引用始終不為0。解決辦法是使用變量保存所需內(nèi)容,并在退出函數(shù)時(shí)將 element 置為 null。

function func() {
  var element = document.getElementById("test"),
      id = element.id;
  element.onClick = function() {
      console.log(id);
  };
  element = null;
}
參考文章

閉包

JavaScript設(shè)計(jì)模式與開發(fā)實(shí)踐

閉包會(huì)造成內(nèi)存泄漏嗎?

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

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/89136.html

相關(guān)文章

  • 《你不知道的javascript筆記_作用域與閉包

    摘要:建筑的頂層代表全局作用域。實(shí)際的塊級作用域遠(yuǎn)不止如此塊級作用域函數(shù)作用域早期盛行的立即執(zhí)行函數(shù)就是為了形成塊級作用域,不污染全局。這便是閉包的特點(diǎn)吧經(jīng)典面試題下面的代碼輸出內(nèi)容答案個(gè)如何處理能夠輸出閉包方式方式下一篇你不知道的筆記 下一篇:《你不知道的javascript》筆記_this 寫在前面 這一系列的筆記是在《javascript高級程序設(shè)計(jì)》讀書筆記系列的升華版本,旨在將零碎...

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

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

    sunsmell 評論0 收藏0
  • 學(xué)習(xí)筆記JavaScript 閉包是怎么通過作用域鏈霸占更多內(nèi)存的?

    摘要:閉包是怎么通過作用域鏈霸占更多內(nèi)存的本文是作者學(xué)習(xí)高級程序設(shè)計(jì)第一小節(jié)的一點(diǎn)個(gè)人理解,詳細(xì)教程請參考原教材。函數(shù)執(zhí)行過程創(chuàng)建了一個(gè)函數(shù)的活動(dòng)對象,作用域鏈的最前端指向這個(gè)對象。函數(shù)執(zhí)行完畢返回值后執(zhí)行環(huán)境作用域鏈和活動(dòng)對象一并銷毀。 JavaScript 閉包是怎么通過作用域鏈霸占更多內(nèi)存的? 本文是作者學(xué)習(xí)《JavaScript 高級程序設(shè)計(jì)》7.2第一小節(jié)的一點(diǎn)個(gè)人理解,詳細(xì)教程請...

    HmyBmny 評論0 收藏0
  • Js學(xué)習(xí)筆記閉包

    摘要:一前言這個(gè)周末,注意力都在學(xué)習(xí)基礎(chǔ)知識上面,剛好看到了閉包這個(gè)神圣的東西,所以打算把這兩天學(xué)到的總結(jié)下來,算是鞏固自己所學(xué)。因此要注意閉包的使用,否則會(huì)導(dǎo)致性能問題。五總結(jié)閉包的作用能夠讀取其他函數(shù)內(nèi)部變量。 # 一、前言 這個(gè)周末,注意力都在學(xué)習(xí)基礎(chǔ)Js知識上面,剛好看到了閉包這個(gè)神圣的東西,所以打算把這兩天學(xué)到的總結(jié)下來,算是鞏固自己所學(xué)。也可能有些不正確的地方,也請大家看到了,麻...

    Crazy_Coder 評論0 收藏0
  • JS筆記

    摘要:從最開始的到封裝后的都在試圖解決異步編程過程中的問題。為了讓編程更美好,我們就需要引入來降低異步編程的復(fù)雜性。異步編程入門的全稱是前端經(jīng)典面試題從輸入到頁面加載發(fā)生了什么這是一篇開發(fā)的科普類文章,涉及到優(yōu)化等多個(gè)方面。 TypeScript 入門教程 從 JavaScript 程序員的角度總結(jié)思考,循序漸進(jìn)的理解 TypeScript。 網(wǎng)絡(luò)基礎(chǔ)知識之 HTTP 協(xié)議 詳細(xì)介紹 HTT...

    rottengeek 評論0 收藏0

發(fā)表評論

0條評論

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