歡迎加入QQ討論群258996829
麥子學(xué)院 頭像
蘋果6袋
6
麥子學(xué)院

JavaScript中閉包的本質(zhì) Javascript中閉包的本質(zhì)是什么?

發(fā)布時(shí)間:2017-08-27 22:48  回復(fù):0  查看:2236   最后回復(fù):2017-08-27 22:48  
本文和大家分享的主要是javascript 中閉包相關(guān)內(nèi)容,一起來(lái)看看吧,希望對(duì)大家 學(xué)習(xí)javascript有所幫助。
  閉包是JavaScript 開發(fā)人員常常談?wù)摰膯?wèn)題,大家普遍對(duì)閉包的認(rèn)知如下:
  模糊的認(rèn)知:閉包是定義在函數(shù)內(nèi)部的函數(shù);
  清晰的認(rèn)知:閉包是會(huì)保存它引用到的外部變量的特殊函數(shù);
其實(shí)在JavaScript 語(yǔ)言中,以上 2 種認(rèn)知都是錯(cuò)誤的;為了幫助大家正確地認(rèn)識(shí)閉包,現(xiàn)分享出我對(duì)閉包的研究和理解,如下:
   1. 閉包
  我對(duì)閉包的定義是:
  閉包的標(biāo)準(zhǔn)定義:攜帶外部變量的函數(shù)稱為閉包;
  我之所以這樣對(duì)閉包下定義,是因?yàn)檫@個(gè)定義幾乎適用所有語(yǔ)言的閉包,如:Object-C Swift 、 JavaScript 等等;所以我認(rèn)為這是較標(biāo)準(zhǔn)的定義;
  對(duì)于JavaScript 中的閉包雖然符合標(biāo)準(zhǔn)定義,但是由于 JavaScript 語(yǔ)言的一些特性,使得 JavaScript 中的閉包的實(shí)現(xiàn)與其它語(yǔ)言(如: Object-C 、 Swift )的實(shí)現(xiàn)并不一樣;
  很多人都認(rèn)為閉包只會(huì)攜帶它內(nèi)部引用的外部變量,并不會(huì)攜帶沒有引用的外部變量,其實(shí)這是錯(cuò)誤的;可以通過(guò)下面的代碼證明:
   function  outFun() {
   var outArg1 = " 外部參數(shù) 1";
   var outArg2 = " 外部參數(shù) 2";
   function  outArg3() {
  console.log(" 外部參數(shù) 3");
  }
  /* 定義閉包
  * codeStr :字符串類型的參數(shù),該參數(shù)的值將被當(dāng)作代碼執(zhí)行
  * return  : 返回將 codeStr 作為代碼執(zhí)行的結(jié)果;
  * */
   function  closureFun(codeStr) {
  console.log(" 閉包引用的變量的值: ",outArg1);
   return eval(codeStr);   // 返回將 codeStr 作為代碼執(zhí)行的結(jié)果;
  }
   return closureFun;
  }
   var getValueOf  = outFun();     // 獲取閉包
   var arg2Value = getValueOf("outArg2");      // 嘗試獲取閉包內(nèi)沒有引用的變量 outArg2 的值; console.log(arg2Value);     // 輸出結(jié)果為:外部參數(shù) 2
   var arg3Value = getValueOf("outArg3");      // 嘗試獲取閉包內(nèi)沒有引用的函數(shù) outArg3 ;
  arg3Value();     // 輸出結(jié)果為:外部參數(shù) 3
  從示例代碼中的運(yùn)行結(jié)果中可以看出,對(duì)于閉包引用到的外部變量outArg1  和 閉包沒有引用到的變量 outArg2 和函數(shù) outArg3 ,在閉包執(zhí)行時(shí)都能被正確地訪問(wèn)到,所以閉包會(huì)攜帶所有的外部變量(函數(shù)也是變量);
  為什么會(huì)這樣呢?若要理解,還需先了解一下作用域鏈的知識(shí),下面是我對(duì)JavaScript 的作用域鏈的理解:
   2. 作用域鏈的理解
  1.  可以把作用域鏈理解成是一個(gè)棧結(jié)構(gòu);
  2.  每個(gè)作用域都有一個(gè)作用域?qū)ο笥糜诒4嬖谠撟饔糜騼?nèi)創(chuàng)建的變量 ( 包括函數(shù) ) ,其保存的方式是:在作用域內(nèi)創(chuàng)建的變量會(huì)成為作用域?qū)ο蟮膶傩裕?/span>
  3.  作用鏈鏈保存的是各級(jí)作用域?qū)ο蟮囊?,其中最近的作用域的作用域?qū)ο笤谧钋岸耍竭h(yuǎn)的作用域的作用域?qū)ο笤娇亢螅?/span>
  4.  全局作用域的作用域?qū)ο笫侨謱?duì)象本身;所以,每個(gè)作用域鏈的最后端都是全局對(duì)象的引用;
  5.  在全局作用域內(nèi)創(chuàng)建的變量會(huì)成為全局對(duì)象的屬性的原因:由于 2( 在作用域內(nèi)創(chuàng)建的變量會(huì)成為作用域?qū)ο蟮膶傩?/span> ) 4( 全局作用域的作用域?qū)ο笫侨謱?duì)象本身 ) ,所以在全局作用域創(chuàng)建的變量會(huì)成為全局對(duì)象的屬性;
  6.  函數(shù)的作用域鏈?zhǔn)窃诤瘮?shù)對(duì)象被創(chuàng)建時(shí)(被定義時(shí))創(chuàng)建的;
  7.  每當(dāng)函數(shù)被執(zhí)行時(shí),都會(huì)新創(chuàng)建一個(gè)函數(shù)的作用域?qū)ο?,并把該作用域?qū)ο笸频阶饔糜蜴湹淖钋岸耍?/span>
  8.  第當(dāng)函數(shù)執(zhí)行結(jié)束時(shí),都會(huì)把函數(shù)的作用域?qū)ο髲脑摵瘮?shù)作用鏈中推出;
   3. 閉包的本質(zhì)
  其實(shí)閉包攜帶外部變量的機(jī)制并非閉包的特有機(jī)制,它是函數(shù)的作用域鏈的一個(gè)效應(yīng);在JavaScript 中,閉包和普通函數(shù)沒有任何本質(zhì)的區(qū)別,閉包只是函數(shù)在某種使用場(chǎng)景下的一個(gè)名字,就好比兇器只是刀在用于行兇時(shí)的名字;
   JavaScript中的閉包能攜帶外部變量的原因是:
  JavaScript 的函數(shù)在被創(chuàng)建時(shí)(被定義時(shí))會(huì)生成自己的作用域鏈;該作用域鏈會(huì)保存各級(jí)作用域?qū)ο蟮囊?,所?/span> JavaScript 的函數(shù)能夠訪問(wèn)其外部的所有變量;
  說(shuō)見上文的作用域鏈的理解  >
  所以,本質(zhì)上,JavaScript 中的閉包攜帶的不是外部變量,而是外部的作用域?qū)ο螅?/span>


來(lái)源: 簡(jiǎn)書
您還未登錄,請(qǐng)先登錄

熱門帖子

最新帖子

?