最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JavaScript中的閉包(Closure)詳細(xì)介紹

 更新時(shí)間:2014年12月30日 08:47:03   投稿:junjie  
這篇文章主要介紹了JavaScript中的閉包(Closure)詳細(xì)介紹,函數(shù)調(diào)用對(duì)象與變量的作用域鏈、什么是閉包等內(nèi)容,并給出了實(shí)例,需要的朋友可以參考下

閉包是JavaScript中一個(gè)重要的特性,其最大的作用在于保存函數(shù)運(yùn)行過程中的信息。在JavaScript中,閉包的諸多特性源自函數(shù)調(diào)用過程中的作用域鏈上。

 

函數(shù)調(diào)用對(duì)象與變量的作用域鏈

 

對(duì)于JavaScript中的每一次函數(shù)調(diào)用,JavaScript都會(huì)創(chuàng)建一個(gè)局部對(duì)象以儲(chǔ)存在該函數(shù)中定義的局部變量;如果在該函數(shù)內(nèi)部還有一個(gè)嵌套定義的函數(shù)(nested function),那么JavaScript會(huì)在已經(jīng)定義的局部對(duì)象之上再定義一個(gè)嵌套局部對(duì)象。對(duì)于一個(gè)函數(shù),其內(nèi)部有多少層的嵌套函數(shù)定義,也就有多少層的嵌套局部對(duì)象。該局部對(duì)象稱為“函數(shù)調(diào)用對(duì)象”(ECMAScript 3中的“call object”,ECMAScript 5中改名為“declarative environment record”,但個(gè)人認(rèn)為還是ECMAScript 3中的名稱更容易理解一些)。以下面的函數(shù)調(diào)用為例:


復(fù)制代碼 代碼如下:

function f(x){
  var a = 10;
  return a*x;
}
console.log(f(6));//60

在這個(gè)簡(jiǎn)單的例子中,當(dāng)調(diào)用f()函數(shù)時(shí),JavaScript會(huì)創(chuàng)建一個(gè)f()函數(shù)的調(diào)用對(duì)象(姑且稱之為f_invokeObj),在f_invokeObj對(duì)象內(nèi)部有兩個(gè)屬性:a和x;運(yùn)行f()時(shí),a值為10而x值為6,因此最后的返回結(jié)果為60。圖示如下:

當(dāng)存在函數(shù)嵌套時(shí),JavaScript將創(chuàng)建多個(gè)函數(shù)調(diào)用對(duì)象:


復(fù)制代碼 代碼如下:

function f(x){
  var a = 10;
  return a*g(x);
  function g(b){
    return b*b;
  }
}
console.log(f(6));//360


在這個(gè)例子中,當(dāng)調(diào)用f()函數(shù)時(shí),JavaScript會(huì)創(chuàng)建一個(gè)f()函數(shù)的調(diào)用對(duì)象(f_invokeObj),其內(nèi)部有兩個(gè)屬性a和x,a值為10而x值為6;運(yùn)行f()時(shí),JavaScript會(huì)對(duì)f()函數(shù)中的g()函數(shù)進(jìn)行解析定義,并創(chuàng)建g()的調(diào)用對(duì)象(g_invokeObj),其內(nèi)部有一個(gè)屬性b,b值與傳入?yún)?shù)x相同為6,因此最后的返回結(jié)果為360。圖示如下:

可以看到,函數(shù)調(diào)用對(duì)象形成了一條鏈。當(dāng)內(nèi)嵌函數(shù)g()運(yùn)行,需要獲取變量值的時(shí)候,會(huì)從最近的函數(shù)調(diào)用對(duì)象中開始進(jìn)行搜索,如果無法搜索到,則沿函數(shù)調(diào)用對(duì)象鏈在更遠(yuǎn)的調(diào)用對(duì)象中進(jìn)行搜尋,此即所謂的“變量的作用域鏈”。如果兩個(gè)函數(shù)調(diào)用對(duì)象中出現(xiàn)相同的變量,則函數(shù)會(huì)取離自己最近的那個(gè)調(diào)用對(duì)象中的變量值:


復(fù)制代碼 代碼如下:

function f(x){
  var a = 10;
  return a*g(x);
  function g(b){
    var a = 1;
    return b*b*a;
  }
}
console.log(f(6));//360, not 3600


在上面的例子中,g()函數(shù)的調(diào)用對(duì)象(g_invokeObj)和f()函數(shù)的調(diào)用對(duì)象(f_invokeObj)中均存在變量a且a的值不同,當(dāng)運(yùn)行g(shù)()函數(shù)時(shí),在g()函數(shù)內(nèi)部所使用的a值為1,而在g()函數(shù)外部所使用的a值則為10。圖示此時(shí)的函數(shù)調(diào)用對(duì)象鏈如下:

什么是閉包?

在JavaScript中所有的函數(shù)(function)都是對(duì)象,而定義函數(shù)時(shí)都會(huì)產(chǎn)生相應(yīng)的函數(shù)調(diào)用對(duì)象鏈,一次函數(shù)定義對(duì)應(yīng)一個(gè)函數(shù)調(diào)用對(duì)象鏈。只要函數(shù)對(duì)象存在,相應(yīng)的函數(shù)調(diào)用對(duì)象就存在;一旦某函數(shù)不再被使用,相應(yīng)的函數(shù)調(diào)用對(duì)象就會(huì)被垃圾回收掉;而這種函數(shù)對(duì)象和函數(shù)調(diào)用對(duì)象鏈之間的一一組合,就稱之為“閉包”。在上面f()函數(shù)和g()函數(shù)的例子中,就存在兩個(gè)閉包:f()函數(shù)對(duì)象和f_invokeObj對(duì)象組成了一個(gè)閉包,而g()函數(shù)對(duì)象和g_invokeObj-f_invokeObj對(duì)象鏈一起組成了第二個(gè)閉包。當(dāng)g()函數(shù)執(zhí)行完畢后,由于g()函數(shù)不再被使用,因此g()閉包被垃圾回收了;之后,當(dāng)f()函數(shù)執(zhí)行完畢后,由于同樣的原因,f()閉包也被垃圾回收了。

從閉包的定義可以得出結(jié)論:所有的JavaScript函數(shù)在定義后都是閉包 – 因?yàn)樗械暮瘮?shù)都是對(duì)象,所有的函數(shù)在執(zhí)行后也都有其對(duì)應(yīng)的調(diào)用對(duì)象鏈。

不過,令閉包真正發(fā)揮作用的是嵌套函數(shù)的情況。由于內(nèi)嵌函數(shù)是在外部函數(shù)運(yùn)行的時(shí)候才開始定義的,因此內(nèi)嵌函數(shù)的閉包中所保存的變量值(尤其是外部函數(shù)的局部變量值)是這次運(yùn)行過程中的值。只要內(nèi)嵌函數(shù)對(duì)象依然存在,那么其閉包就依然存在(閉包中的變量值不會(huì)發(fā)生任何改變),從而也就實(shí)現(xiàn)了保存函數(shù)運(yùn)行過程的信息這個(gè)目的??紤]以下這個(gè)例子:


復(fù)制代碼 代碼如下:

var a = "outside";
function f(){
  var a = "inside";
  function g(){return a;}
  return g;
}
var result = f();
console.log(result());//inside


在這個(gè)例子中,當(dāng)運(yùn)行f()函數(shù)時(shí),g()函數(shù)被定義,同時(shí)創(chuàng)建了g()函數(shù)的閉包,g()閉包包含了g_invokeObj-f_invokeObj對(duì)象鏈,因此保存了f()函數(shù)執(zhí)行過程中的變量a的值。當(dāng)執(zhí)行console.log()語句時(shí),由于g函數(shù)對(duì)象仍然存在,因此g()閉包也依然存在;當(dāng)運(yùn)行這個(gè)仍然存在的g函數(shù)對(duì)象時(shí),JavaScript會(huì)使用依然存在的g()閉包并從中獲取變量a的值(“inside”)。

相關(guān)文章

最新評(píng)論

峡江县| 勃利县| 江西省| 监利县| 兴山县| 西藏| 都兰县| 瑞安市| 石柱| 永定县| 保靖县| 澄江县| 沭阳县| 九寨沟县| 三河市| 兴海县| 临颍县| 隆安县| 澄江县| 仪征市| 兴化市| 武威市| 札达县| 咸阳市| 玉树县| 胶州市| 奉新县| 呈贡县| 罗定市| 长垣县| 涡阳县| 临江市| 奇台县| 东宁县| 武邑县| 额济纳旗| 开鲁县| 邹城市| 华容县| 齐齐哈尔市| 屏边|