亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

JS進擊之路:閉包

tolerious / 2546人閱讀

摘要:常見問題說到閉包相關(guān)的問題,最典型的就是變量和指向這兩類問題。如果有錯誤或不嚴謹?shù)牡胤剑瑲g迎批評指正,如果喜歡,歡迎點贊。

引言

閉包這個詞對很多前端開發(fā)人員來說既熟悉又陌生,熟悉是因為很多人都用過閉包,但是用的時候不知道閉包,陌生是因為并不理解閉包,接下來這篇文章將會從多方面介紹閉包

定義

閉包是怎么定義的呢?當函數(shù)可以記住并訪問所在的詞法作用域時,就產(chǎn)生了閉包,即使函數(shù)在當前詞法作用域之外執(zhí)行。來看一個具體例子:

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

函數(shù)bar的詞法作用域可以訪問foo的內(nèi)部作用域,并且bar在被作為返回值賦值給baz執(zhí)行時,bar函數(shù)在定義時的詞法作用域以外的地方被調(diào)用,依然可以訪問foo函數(shù)的內(nèi)部作用域變量a,這就是閉包

分析

現(xiàn)在讓我們來看為什么閉包可以在定義的詞法作用域外記住并且訪問定義時的詞法作用域的變量,想要一探究竟,先來看一個簡單的例子來函數(shù)的執(zhí)行過程:

function foo (a) {
  console.log(a)
}
foo (a)


上面是一個簡單的函數(shù)調(diào)用,以及在執(zhí)行時的上下文環(huán)境,重點看執(zhí)行時上下文環(huán)境,在創(chuàng)建foo函數(shù)時,會創(chuàng)建一個預(yù)先包含全局變量對象的作用域鏈,這個作用域鏈被保存在內(nèi)部的[[Scope]]屬性中,當調(diào)用foo()函數(shù)時,會為函數(shù)創(chuàng)建一個執(zhí)行環(huán)境,然后通過復(fù)制函數(shù)的[[Scope]屬性中的對象構(gòu)建起執(zhí)行環(huán)境的作用域鏈。此后,又有一個活動對象(包含this、arguments、a)被創(chuàng)建并被推入執(zhí)行環(huán)境作用域鏈的前端,對于foo函數(shù)來說,其作用域鏈包含兩個變量對象,一個時全局的變量對象,一個是局部的活動變量對象,一般來說當函數(shù)執(zhí)行完成后,局部的活動變量對象會被銷毀,只留全局的,但是閉包執(zhí)行過程有所不同,來看具體例子:

function foo () {
  var a = 2
  function bar (b) {
    console.log(a + b)
  }
  return bar
}
var baz = foo()
baz(3) //5


接下來來分析下上面閉包的執(zhí)行上下環(huán)境,在一個函數(shù)內(nèi)部定義的函數(shù)會將包含函數(shù)的活動對象添加到它的作用域鏈中,因此,bar函數(shù)的作用域鏈中會包含foo函數(shù)的活動對象,在bar函數(shù)從foo中被返回后,它的作用域鏈條被初始化為全局變量和foo中活動對象,因此,bar函數(shù)可以訪問foo函數(shù)中定義的所有變量,同時foo函數(shù)在執(zhí)行完畢后,其活動對象也不會被銷毀,因為bar函數(shù)的作用域鏈仍然在引用這個活動對象。

常見問題

說到閉包相關(guān)的問題,最典型的就是變量和this指向這兩類問題。

變量
function test () {
  var result = new Array()
  for (var i = 0; i < 6; i++) {
    result[i] = function () {
      return i
    }
  }
  return result
}


上面的代碼展示就是面試題里面經(jīng)常會碰到,result的結(jié)果從上面截圖能看到,作用域中保存的i都是6,這是為什么呢?因為閉包保存的是函數(shù)中的活動對象,因此它們引用的都是同一個變量,并且是變量的最后一個值,因此都是6,那這個問題怎么解決呢?最常見的最簡單肯定是將var換成let,也可以像下面這樣:

function test () {
  var result = new Array()
  for (var i = 0; i < 6; i++) {
    result[i] = (function () {
      return i
    })()
  }
  return result
}

將閉包直接改成一個自執(zhí)行函數(shù),自執(zhí)行函數(shù)本身是沒有變量作用域的,因此會使用外層函數(shù)的變量作用域,這樣也能達到我們想要的效果

this指向
var name = "window"
var obj = {
  name: "object",
  getName: function () {
    return function () {
      return this.name
    }
  }
}
console.log(obj.getName()())

上面這段js代碼的this.name的返回值是window,這是為什么呢?按照上面寫到的,此匿名函數(shù)在執(zhí)行過程中,它的作用域會包含三部分:自身的活動對象、getName函數(shù)的活動對象和全局的變量對象,同時每個活動對象自動取得兩個特殊的變量:this和arguments,但是內(nèi)部函數(shù)在查找this時是無法直接訪問外部函數(shù)的this變量,因此會沿著作用域鏈去查找全局變量中繼續(xù)查找,如果想要取外部函數(shù)中的this取值也很簡單,只需要向下面代碼這樣:

var name = "window"
var obj = {
  name: "object",
  getName: function () {
    var that = this
    return function () {
      return that.name
    }
  }
}
console.log(obj.getName()())

將this賦值給一個變量,內(nèi)部函數(shù)是可以訪問外部函數(shù)變量的,這樣就解決了

總結(jié)

閉包是一個容易混淆不清的概念,這篇文章對閉包的定義、執(zhí)行、常見問題做了簡單的介紹,希望通過這篇能對大家理解和使用閉包有所幫助。如果有錯誤或不嚴謹?shù)牡胤?,歡迎批評指正,如果喜歡,歡迎點贊。

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

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

相關(guān)文章

  • 進擊的 JavaScript(五) 之 立即執(zhí)行函數(shù)與閉包

    摘要:匿名函數(shù)是不能單獨寫的,所以就提不上立即執(zhí)行了。六立即執(zhí)行函數(shù)在閉包中的應(yīng)用立即執(zhí)行函數(shù)能配合閉包保存狀態(tài)。來看下上節(jié)內(nèi)容中閉包的例子現(xiàn)在,我們來利用立即執(zhí)行函數(shù)來簡化它第一個匿名函數(shù)執(zhí)行完畢后,返回了第二個匿名函數(shù)。 前面的閉包中,提到與閉包相似的立即執(zhí)行函數(shù),感覺兩者還是比較容易弄混吧,嚴格來說(因為犀牛書和高程對閉包的定義不同),立即執(zhí)行函數(shù)并不屬于閉包,它不滿足閉包的三個條件。...

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

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

    cyixlq 評論0 收藏0
  • JS進擊之路:作用域

    摘要:如果是,編譯器會忽略該聲明,繼續(xù)進行編譯否則它會要求作用域在當前作用域的集合中聲明一個新的變量接下來編譯器會為引擎生成運行時所需的代碼,這些代碼被用來處理這個賦值操作。引擎運行時會首先詢問作用域,在當前的作用域集合中是否存在一個叫做的變量。 引言 幾乎所有的編程語言都有作用域的概念,那作用域到底指的是什么呢?作用域就是編程語言在定義變量時,變量如何存儲、變量如何訪問的一套規(guī)則,不同的編...

    el09xccxy 評論0 收藏0
  • 進擊的 JavaScript(四) 之 閉包

    摘要:此時產(chǎn)生了閉包。導(dǎo)致,函數(shù)的活動對象沒有被銷毀。是不是跟你想的不一樣其實,這個例子重點就在函數(shù)上,這個函數(shù)的第一個參數(shù)接受一個函數(shù)作為回調(diào)函數(shù),這個回調(diào)函數(shù)并不會立即執(zhí)行,它會在當前代碼執(zhí)行完,并在給定的時間后執(zhí)行。 上一節(jié)說了執(zhí)行上下文,這節(jié)咱們就乘勝追擊來搞搞閉包!頭疼的東西讓你不再頭疼! 一、函數(shù)也是引用類型的。 function f(){ console.log(not cha...

    Anleb 評論0 收藏0
  • 我的前端進階之路

    摘要:事件模型事件捕獲階段。事件到達目標元素觸發(fā)目標元素的監(jiān)聽函數(shù)。的狀態(tài)值與狀態(tài)碼的狀態(tài)值未初始化還沒有調(diào)用方法。載入完成已經(jīng)執(zhí)行完成,已經(jīng)接收到全部的響應(yīng)內(nèi)容。 前言 總括: 包含這三個月來碰到的一些覺得比較好的面試題,三個月沒怎么寫博客著實有些手癢,哈哈哈。7000余字,不成敬意2333 原文地址:我的前端進階之路 知乎專欄&&簡書專題:前端進擊者(知乎)&&前端進擊者(簡書) 博主...

    cloud 評論0 收藏0

發(fā)表評論

0條評論

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