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

資訊專欄INFORMATION COLUMN

學(xué)習JavaScript之閉包

shiguibiao / 1450人閱讀

摘要:閉包在我的前端學(xué)習中一直也是盲點,之前很多次看到別人提到我都是完全聽不懂。閉包導(dǎo)致的問題因為閉包會使得函數(shù)中的變量都保存在內(nèi)存中,如不能及時釋放會對性能造成影響。

閉包在我的前端學(xué)習中一直也是盲點,之前很多次看到別人提到我都是完全聽不懂。最近一直看書和寫demo,對閉包也逐漸有所理解了,在這里寫下這篇博客。

從作用域鏈講起

首先明確幾個概念:
1.JavaScript有函數(shù)級作用域,但沒有塊級作用域。
2.當要使用一個變量時,會沿著作用域鏈一步一步向上查找。
這里有一個demo:

var a = 1

function foo () {
  var a = 2
}

foo()
console.log(a) // a = 1

結(jié)果當然是a = 1,雖然在foo函數(shù)中重新聲明了a并且賦給它一個新的值,但是var聲明的變量只在foo()函數(shù)中有效,函數(shù)執(zhí)行完畢就會銷毀,因此全局作用域中a的值沒有變化。
接下來再看這個demo:

for (var i = 0; i < 10; i++) {
  // code
}

console.log(i) // i = 10

這里在for循環(huán)結(jié)束之后仍然能在外部訪問到i,就是因為JavaScript沒有塊級作用域造成的。

閉包的特性

閉包的主要特性就是可以從外部訪問函數(shù)內(nèi)部的屬性和方法。先看一個demo:

function foo () {
  var a = 1
}
foo()
console.log(a) // 出錯

正常情況下,定義在函數(shù)內(nèi)部的局部變量在函數(shù)執(zhí)行完之后就會被銷毀,因此在外部是無法訪問局部變量的。那應(yīng)該怎么做才能訪問呢?請繼續(xù)看:

function foo () {
  var a = 1
  function bar () {
    console.log(a)
  }
  return bar
}
var baz = foo()
baz() // 1

在這個demo中,我們在函數(shù)foo()內(nèi)部又定義了一個函數(shù)bar(),并把它的函數(shù)名返回,這樣便能在外部實現(xiàn)對內(nèi)部變量a的訪問。

有人問了:不是說函數(shù)執(zhí)行結(jié)束之后內(nèi)部變量會被銷毀嗎?你這不科學(xué)啊。

是的,原來函數(shù)執(zhí)行結(jié)束之后內(nèi)部變量的確會被銷毀,但是這里內(nèi)部函數(shù)bar()在foo()執(zhí)行時被返回并保存到了外部的baz中。這時候foo()執(zhí)行完后,baz中依舊保存著對函數(shù)bar()的引用,因此bar()的作用域并沒有被釋放,根據(jù)之前提到的變量查找方式,在bar()函數(shù)的外層作用域中找到了a。

以上就是使用閉包能從外部訪問內(nèi)部屬性的原理。

閉包的用途

利用閉包強大的特性,最方便的用途就是實現(xiàn)私有變量和私有方法;另外,因為使用閉包會在內(nèi)存中保存函數(shù)作用域,因此也能保存變量的值。

此話怎解?請看下面的demo:

for (var i = 1; i <= 5; i++) {
  setTimeout(function timer () {
    console.log(i)
  }, i * 1000)
} // 6 6 6 6 6

這里的結(jié)果并不是我們預(yù)想中的每隔一秒依次輸出12345,而是每隔一秒輸出一個6,為什么會這樣呢?

首先,這個6是變量i最終退出循環(huán)時的值,其次var聲明的變量沒有塊級作用域,因此i實際上在全局作用域中都訪問得到。到這里不難理解了,setTimeout在循環(huán)結(jié)束后執(zhí)行timer()函數(shù)時,訪問的i實際上在全局作用域中,此時i=6,因此后面的每個timer()函數(shù)執(zhí)行訪問的i都是6。那么問題又來了,怎樣才能讓閉包訪問的i是我們想要的呢?

其實很簡單,讓i變成局部變量,在循環(huán)結(jié)束之后銷毀,這樣每個閉包訪問的就是保存在作用域中的局部變量i,也就是對應(yīng)的12345。請看下面的demo:

for (var i = 1; i <= 5; i++) {
  (function (j) {
    setTimeout(function timer () {
      console.log(j)
    }, j * 1000)
  })(i)
} // 1 2 3 4 5

這里用到了立即執(zhí)行函數(shù)(IIFE),可能有些難以理解。那我一步一步解釋:立即執(zhí)行函數(shù)其實就是JavaScript模仿塊級作用域的方法,這里你可以把它簡單看成一個函數(shù)調(diào)用。i就是傳給調(diào)用函數(shù)的參數(shù),內(nèi)部匿名函數(shù)的形參j接收到i的值開始執(zhí)行setTimeout。此時j就是函數(shù)級作用域中的局部變量,在循環(huán)結(jié)束后,timer()函數(shù)開始執(zhí)行,因為它是一個閉包,所以能訪問保存在作用域中的變量j,也就輸出了我們想要的結(jié)果。

當然更簡單的方式是用ES6的let來聲明i,這樣也是使得i變成局部變量,其他關(guān)于ES6這里就不多提,有興趣的可以自行看let基本用法。

閉包導(dǎo)致的問題

1.因為閉包會使得函數(shù)中的變量都保存在內(nèi)存中,如不能及時釋放會對性能造成影響。
2.在IE9以下的瀏覽器會有內(nèi)存泄漏的問題。(關(guān)于這塊我后續(xù)會寫文章詳細說明)

本人經(jīng)驗尚淺,目前對于前端仍在不斷摸索和學(xué)習,文章如有錯誤,歡迎各位指正。最后附上本人博客地址和原文鏈接,希望能向各位多多學(xué)習。

lbj的前端之路
原文鏈接:學(xué)習JavaScript之原型鏈

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

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

相關(guān)文章

  • 學(xué)習JavaScript內(nèi)存泄漏

    摘要:接上回我寫了一篇關(guān)于閉包的博客學(xué)習之閉包,最后談到閉包導(dǎo)致的問題時留了一個尾在以下的瀏覽器中會有內(nèi)存泄漏的問題。今天的博客就繼續(xù)探索一下內(nèi)存泄漏的問題。博客地址的前端之路原文鏈接學(xué)習之內(nèi)存泄漏 接上回我寫了一篇關(guān)于閉包的博客《學(xué)習JavaScript之閉包》, 最后談到閉包導(dǎo)致的問題時留了一個尾: 在IE9以下的瀏覽器中會有內(nèi)存泄漏的問題。 今天的博客就繼續(xù)探索一下內(nèi)存泄漏的問題。 淺...

    nodejh 評論0 收藏0
  • JS筆記

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

    rottengeek 評論0 收藏0
  • 前端學(xué)習筆記閉包——看了一張圖終于明白啥是閉包

    摘要:在一個閉包環(huán)境內(nèi)修改變量值,不會影響另一個閉包中的變量。直到看到函數(shù)閉包閉包這篇文章的代碼一部分,終于明白其中的邏輯了。 閉包 閉包定義:指擁有多個變量和綁定了這些變量的環(huán)境的表達式(通常是一個函數(shù)),因而這些變量也是該表達式的一部分。函數(shù)內(nèi)部可以直接讀取全局變量。函數(shù)內(nèi)部變量無法在函數(shù)外部訪問。函數(shù)內(nèi)部聲明要用var或者let聲明,不然會變成全局變量鏈式作用域:子對象會一級級向上尋找...

    andycall 評論0 收藏0
  • 進擊JavaScript(三)玩轉(zhuǎn)閉包

    摘要:為了更好的理解,在閱讀此文之前建議先閱讀上一篇進擊之詞法作用域與作用域鏈什么是閉包閉包的含義就是閉合,包起來,簡單的來說,就是一個具有封閉功能與包裹功能的結(jié)構(gòu)。在中函數(shù)構(gòu)成閉包。 為了更好的理解,在閱讀此文之前建議先閱讀上一篇《進擊JavaScript之詞法作用域與作用域鏈》 1.什么是閉包 閉包的含義就是閉合,包起來,簡單的來說,就是一個具有封閉功能與包裹功能的結(jié)構(gòu)。所謂的閉包就是...

    cyixlq 評論0 收藏0
  • Deep in JS - 收藏集 - 掘金

    摘要:今天同學(xué)去面試,做了兩道面試題全部做錯了,發(fā)過來給道典型的面試題前端掘金在界中,開發(fā)人員的需求量一直居高不下。 排序算法 -- JavaScript 標準參考教程(alpha) - 前端 - 掘金來自《JavaScript 標準參考教程(alpha)》,by 阮一峰 目錄 冒泡排序 簡介 算法實現(xiàn) 選擇排序 簡介 算法實現(xiàn) ... 圖例詳解那道 setTimeout 與循環(huán)閉包的經(jīng)典面...

    enali 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<