欧美一级特黄大片做受成人-亚洲成人一区二区电影-激情熟女一区二区三区-日韩专区欧美专区国产专区

javascript中的閉包是什么

JavaScript 一個(gè)近乎神話 對(duì)于JavaScript有使用經(jīng)驗(yàn)但卻從未真正理解閉包概念的人來(lái)說(shuō),理解閉包可以說(shuō)是某種意義上的重生。閉包并不是需要學(xué)習(xí)新的語(yǔ)法才能使用的工具。閉包的產(chǎn)生是基于詞法作用域?qū)懘a時(shí)自然產(chǎn)生的結(jié)果。換句話說(shuō),你不需要要為了閉包而寫(xiě)閉包,閉包在我們寫(xiě)的代碼中隨處可見(jiàn)。 當(dāng)你真正了解閉包之后,會(huì)發(fā)現(xiàn),哦~,原來(lái)我以前所敲的代碼中已經(jīng)出現(xiàn)了很多閉包了鴨!

成都創(chuàng)新互聯(lián)專業(yè)為企業(yè)提供昌江網(wǎng)站建設(shè)、昌江做網(wǎng)站、昌江網(wǎng)站設(shè)計(jì)、昌江網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁(yè)設(shè)計(jì)與制作、昌江企業(yè)網(wǎng)站模板建站服務(wù),十載昌江做網(wǎng)站經(jīng)驗(yàn),不只是建網(wǎng)站,更提供有價(jià)值的思路和整體網(wǎng)絡(luò)服務(wù)。

一個(gè)小 demo


仔細(xì)看看下面的例子我們會(huì)感到奇怪,明明都是調(diào)用result(),為什么結(jié)果會(huì)不一樣呢?

let count=500 //全局作用域
function foo1() {
  let count = 0;//函數(shù)全局作用域
  function foo2() {
    count++;//函數(shù)內(nèi)部作用域
    console.log(count);
    return count;
  }
  return foo2;//返回函數(shù)
}
let result = foo1();
result();//結(jié)果為1
result();//結(jié)果為2

首先f(wàn)oo1()返回的是一個(gè)foo2()函數(shù),當(dāng)我們調(diào)用result()的時(shí)候就會(huì)返回foo2()執(zhí)行的函數(shù),foo2()里面有什么呢? 首先我們看到如下有一個(gè)count變量,但是沒(méi)有定義.我們根據(jù)JavaScript的作用域鏈的定義可知,當(dāng)函數(shù)內(nèi)部的變量沒(méi)有定義的時(shí)候,就會(huì)采用冒泡的方式,向上一級(jí)尋找.上一級(jí)沒(méi)有接著上一級(jí)找,直到最頂層window. 如果都沒(méi)有,就會(huì)報(bào)undefined的錯(cuò)誤.這里我們?cè)趂oo1()中找到了count,于是count+1,第一次輸出的是1,沒(méi)有什么問(wèn)題.

 function foo2() {
    count++;
    console.log(count);
    return count;
  }

但是第二次我們?cè)賵?zhí)行result()的時(shí)候就出現(xiàn)了問(wèn)題,為什么會(huì)是2呢?按照流程,首先再foo2()函數(shù)內(nèi)部尋找count,沒(méi)有然后到外層尋找,找到了count=0,這時(shí)候count+1應(yīng)該為1才對(duì).這里就涉及到閉包的問(wèn)題了.

javascript中的閉包是什么

首先我們?cè)谠瓉?lái)的代碼中加一個(gè)debugger,然后到谷歌瀏覽器右鍵檢查,點(diǎn)擊resources就可以看到右邊有一個(gè)Closure,瀏覽器的可視化已經(jīng)證實(shí)了這的確是一個(gè)閉包.并且count=1已經(jīng)存儲(chǔ)在了Closure之中.也就說(shuō)明count=1沒(méi)有被銷毀,等下次在調(diào)用result()的時(shí)候count=2.

認(rèn)識(shí)作用域


要學(xué)習(xí)Clusure必須了解JavaScript的作用域相關(guān)知識(shí) 作用域包括:

1.全局作用域
2.函數(shù)作用域
4.塊級(jí)作用域(es6 新出,解決 var 問(wèn)題, 新增 let, const)

  var count = 100; //全局作用域
  function foo1() {
    var count = 0; //函數(shù)全局作用域
    return count; //返回函數(shù)
  }
  if (count == 1) {
    //塊級(jí)作用域
    console.log(count);
  }

上面代碼簡(jiǎn)單可以看出作用域分類,需要注意是,一個(gè)函數(shù)(function)也是塊級(jí)作用域,簡(jiǎn)單來(lái)說(shuō),一般有 {}都可以算做是一個(gè)塊級(jí)作用域.

作用域鏈


作用域里面嵌套作用域,就形成了作用域鏈. 外部作用域無(wú)法訪問(wèn)內(nèi)部的作用域,看如下例子

function foo(){
var n=1
function foo2(){
  var m=1
  console.log(n) //1
}
foo2()
}
foo()
console.log(n) //err: n is not defined

上述代碼中在全局中無(wú)法訪問(wèn)內(nèi)部的n,但是在嵌套的內(nèi)部foo2()可以訪問(wèn)外部的函數(shù),這就是作用域產(chǎn)生的特殊效果.

明白了作用域鏈,我們?cè)賮?lái)看個(gè)例子(很有迷惑性,仔細(xì)看看哦):

 var name = 'Mike'; //第一次定義name
  function showName() {
    console.log(name);  //輸出 Mike 還是 Jay ?     
  }

  function changeName() {
    var name = 'Jay'; //重新定義name
    showName(); //調(diào)用showName()
  }
  changeName();

上面的例子你覺(jué)得輸出的是什么呢?答案是Mike.在這里我們引出了一個(gè)新的概念,詞法作用域作用域有兩種模型:

  • 詞法作用域(靜態(tài)):js查找是按照代碼書(shū)寫(xiě)時(shí)候的位置來(lái)決定的,而不是按照調(diào)用時(shí)候位置

  • 動(dòng)態(tài)作用域:目前還有使用的有Perl,Bash (可以自行了解)

javascript中的閉包是什么

通過(guò)詞法作用域的的規(guī)則我們可以再來(lái)分析一下

  1. 調(diào)用changeName()時(shí),找到這個(gè)函數(shù)

  2. 定義var name = "Jay"

  3. 調(diào)用showName()

  4. 在changeName()里面查找是否有showName()這個(gè)方法,發(fā)現(xiàn)沒(méi)有,向外層查找,找到了

  5. 調(diào)用console.log(name),在函數(shù)內(nèi)部查找有沒(méi)有name,沒(méi)有,向外查找,找到了,name="Mike"

  6. 輸出Mike

閉包


了解了上面的知識(shí)之后,終于來(lái)到了閉包

閉包在兩本書(shū)上的官方解釋:

1.小"黃"書(shū)(你不知道的JavaScript): 當(dāng)函數(shù)可以記住并訪問(wèn)所在的詞法作用域時(shí),就產(chǎn)生了閉包,即使函數(shù)是在當(dāng)前詞法作用域之外執(zhí)行.
2.紅寶書(shū)(JavaScript高級(jí)程序設(shè)計(jì)): 閉包是指有權(quán)訪問(wèn)另一個(gè) 函數(shù)作用域中的變量的函數(shù)

非常抽象的一個(gè)概念,我自己的一個(gè)理解是:
當(dāng)一個(gè)變量(就像上面的name)既不是該函數(shù)內(nèi)部的局部變量,也不是該函數(shù)的參數(shù),相對(duì)于作用域來(lái)說(shuō),就是一個(gè)自由變量(引用了外部變量),這樣就會(huì)形成一個(gè)閉包.
怎么說(shuō)呢?我們?cè)賮?lái)看看一開(kāi)始我們使用的demo

let count = 500; //全局作用域
function foo1() {
  let count = 0; //函數(shù)全局作用域
  function foo2() {
    let count2 = 1; //隨便新增一個(gè)變量
    // count++;  注釋
    debugger;
    //console.log(count); 注釋
    //return count;  注釋
  }
  return foo2; //返回函數(shù)
}
let result = foo1();
result(); //結(jié)果為1
result(); //結(jié)果為2

再次使用瀏覽器看看,這時(shí)我們就發(fā)現(xiàn)Closure已經(jīng)消失了,這也就證實(shí)我說(shuō)的,如果函數(shù)內(nèi)部不調(diào)用外部的變量,就不會(huì)形成閉包.但是如果調(diào)用了外部變量,那么就會(huì)形成閉包. 這也就是說(shuō)不是所有的函數(shù)嵌套函數(shù)都能形成閉包

最后我們?cè)賮?lái)看一個(gè)循環(huán)閉包的例子

for (var i = 1; i <= 5; i++) {
  setTimeout(function timer() {
    debugger;
    console.log(i); // 輸出什么?   
  }, 1000);
}

答案 6 6 6 6 6 .因?yàn)閟etTimeout里面的回調(diào)函數(shù)是一個(gè)異步的過(guò)程(異步代表可以不用等待我這個(gè)代碼先執(zhí)行完,可以先往后執(zhí)行),而for循環(huán)是同步的(代碼只能從上往下的執(zhí)行),立即執(zhí)行,異步的setTimeout必須等待一秒才能執(zhí)行,這時(shí)i早已經(jīng)循環(huán)結(jié)束了.
解決辦法有三個(gè):

  1. 將for循環(huán)中的var 改成let

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

這樣就沒(méi)有問(wèn)題了, 因?yàn)閘et是有塊級(jí)的功能,每一層循環(huán)都是獨(dú)立的,互不影響,所以才能正常輸出.
     2. 把setTimeout()套上一個(gè)function

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

這樣同樣能夠?qū)崿F(xiàn)這個(gè)功能,原理和第一個(gè)方法一樣,每一個(gè)log()都是獨(dú)立的,互不影響,這樣才能有正確的結(jié)果,var就是因?yàn)闆](méi)有塊級(jí)的功能,才會(huì)出問(wèn)題 3. 包裝成匿名函數(shù)

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

前面一個(gè)(func..)定義函數(shù),后面一個(gè)(i)調(diào)用,這再JavaScript叫做立即執(zhí)行函數(shù),其實(shí)與第二種方式是一樣的,只是寫(xiě)法不一樣.

結(jié)語(yǔ)


理解JavaScript閉包是一項(xiàng)重要的技能,在面試中也常常會(huì)有,這是邁進(jìn)高級(jí)JavaScript工程師的必經(jīng)之路.

以上就是javascript中的閉包中的閉包的詳細(xì)內(nèi)容,更多請(qǐng)關(guān)注創(chuàng)新互聯(lián)其它相關(guān)文章!

本文標(biāo)題:javascript中的閉包是什么
URL標(biāo)題:http://aaarwkj.com/article40/jjhoeo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站導(dǎo)航、云服務(wù)器、小程序開(kāi)發(fā)、軟件開(kāi)發(fā)標(biāo)簽優(yōu)化、搜索引擎優(yōu)化

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都網(wǎng)頁(yè)設(shè)計(jì)公司
色伊人久久综合中文字幕| av丰满人妻一区二区| 国产成人亚洲精品专区高清| 色播五月麻豆激情综合网| 国产精品亚洲一区二区在| 区二区三区毛片乱码免费| 深夜日本福利在线观看| 漂亮人妻被中出中文字幕| 91精品国产91久久综合福利| 麻豆一区二区人妻网站| 亚洲综合久久国产一区二区| 久久日韩制服丝袜人妻| 亚洲国产熟女一区二区三| 色爱区偷拍人妻中文字幕| av免费在线观看麻豆| 精品国产一区亚洲二区| 日韩av在线免费在线观看| 亚洲国产成人精品女人| 乱色视频中文字幕在线着| 日韩专区欧美二区国产| 亚洲六月丁香六月婷婷| 亚洲综合一区二区在线视频 | 日本人妻三级精品久久| 国产精品午夜福利天堂| 亚洲一区二区精品自拍| 国产熟女av一区二区| 久久超碰一区二区三区| 国产精品网站在线观看| 日本毛茸茸的丰满熟妇| 加勒比久久精品网址系列| 国产亚洲欧美精品久久久久久| 熟妇人妻内射一区二区三区| 亚洲日本乱码一区二区三| 蜜桃av在线观看一区二区| 国产欧美日韩另类视频| 少妇精品偷拍高潮少妇在线观看 | 久久香蕉国产线看观看av| 一区二区蜜桃在线观看| 欧美高清视频免费播放| 天天操天天干蜜桃av| 日产中文乱码字幕无线观看|