国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 編程 > JavaScript > 正文

理解Javascript_15_作用域分配與變量訪問(wèn)規(guī)則,再送個(gè)閉包

2019-11-21 00:11:35
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友
作用域分配與變量訪問(wèn)規(guī)則
  在 ECMAScript 中,函數(shù)也是對(duì)象。函數(shù)對(duì)象在變量實(shí)例化過(guò)程中會(huì)根據(jù)函數(shù)聲明來(lái)創(chuàng)建,或者是在計(jì)算函數(shù)表達(dá)式或調(diào)用 Function 構(gòu)造函數(shù)時(shí)創(chuàng)建。(關(guān)于'函數(shù)對(duì)象'請(qǐng)見(jiàn)《理解Javascript_08_函數(shù)對(duì)象》)。每個(gè)函數(shù)對(duì)象都有一個(gè)內(nèi)部的 [[scope]] 屬性,這個(gè)屬性也由對(duì)象列表(鏈)組成。這個(gè)內(nèi)部的[[scope]] 屬性引用的就是創(chuàng)建它們的執(zhí)行環(huán)境的作用域鏈,同時(shí),當(dāng)前執(zhí)行環(huán)境的活動(dòng)對(duì)象被添加到該對(duì)象列表的頂部。當(dāng)我們?cè)诤瘮?shù)內(nèi)部訪問(wèn)變量時(shí),其實(shí)就是在作用域鏈上尋找變量的過(guò)程。

理論性太強(qiáng)了(總結(jié)死我了!),還是讓我們來(lái)看一段代碼吧:
復(fù)制代碼 代碼如下:

<script type="text/javascript">
function outer(){
var i = 10;
function inner(){
var j = 100;
alert(j);//100
alert(i);//10
alert(adf);
}
inner();
}
outer();
</script>

下圖清晰的展現(xiàn)了上述代碼的內(nèi)存分配與作用域分配情況:

下面來(lái)解釋一下:
1.載入代碼,創(chuàng)建全局執(zhí)行環(huán)境,此時(shí)會(huì)在可變對(duì)象(window)中添加outer變量,其指向于函數(shù)對(duì)象outer,此時(shí)作用域鏈中只有window對(duì)象.
2.執(zhí)行代碼,當(dāng)程序執(zhí)行到outer()時(shí),會(huì)在全局對(duì)象中尋找outer變量,成功調(diào)用。
3.創(chuàng)建outer的執(zhí)行環(huán)境,此時(shí)會(huì)新創(chuàng)建一個(gè)活動(dòng)對(duì)象,添加變量i,設(shè)置值為10,添加變量inner,指向于函數(shù)對(duì)象inner.并將活動(dòng)對(duì)象壓入作用域鏈中.并將函數(shù)對(duì)象outer的[[scope]]屬性指向活動(dòng)對(duì)象outer。此時(shí)作用域鏈為outer的活動(dòng)對(duì)象+window.
4.執(zhí)行代碼,為 i 成功賦值。當(dāng)程序執(zhí)行到inner()時(shí),會(huì)在函數(shù)對(duì)象outer的[[scope]]中尋找inner變量。找到后成功調(diào)用。
5.創(chuàng)建inner的執(zhí)行環(huán)境,新建一個(gè)活動(dòng)對(duì)象,添加變量j,賦值為100,并將該活動(dòng)對(duì)象壓入作用域鏈中,并函數(shù)對(duì)象inner的[[scope]]屬性指向活動(dòng)對(duì)象inner.此時(shí)作用域鏈為:inner的活動(dòng)對(duì)象+outer的活動(dòng)對(duì)象+全局對(duì)象.
6.執(zhí)行代碼為j賦值,當(dāng)訪問(wèn)i、j時(shí)成功在作用域中找到對(duì)應(yīng)的值并輸出,而當(dāng)訪問(wèn)變量adf時(shí),沒(méi)有在作用域中尋找到,訪問(wèn)出錯(cuò)。

注:通過(guò)內(nèi)存圖,我們會(huì)發(fā)現(xiàn)作用域鏈與prototype鏈?zhǔn)侨绱说南嘞蟆_@說(shuō)明了很多問(wèn)題...(仁者見(jiàn)仁智者見(jiàn)智,自己探尋答案吧!)

閉包原理
在我們了解了作用域的問(wèn)題之后,對(duì)于閉包這個(gè)問(wèn)題已經(jīng)很簡(jiǎn)單了。什么是閉包?閉包就是封閉了外部函數(shù)作用域中變量的內(nèi)部函數(shù)。
我們來(lái)看一個(gè)典型的閉包運(yùn)用:生成increment值
復(fù)制代碼 代碼如下:

<script type="text/javascript">
var increment = (function(){
var id = 0;
return function(){
return ++id;
}
})()
alert(increment());//1
alert(increment());//2
</script>

外層匿名函數(shù)返回的是一個(gè)內(nèi)嵌函數(shù),內(nèi)嵌函數(shù)使用了外層匿名函數(shù)的局部變量id。照理外層匿名函數(shù)的局部變量在返回時(shí)就超出了作用域因此increment()調(diào)用無(wú)法使用才對(duì)。這就是閉包Closure,即函數(shù)調(diào)用返回了一個(gè)內(nèi)嵌函數(shù),而內(nèi)嵌函數(shù)引用了外部函數(shù)的局部變量、參數(shù)等這些應(yīng)當(dāng)被關(guān)閉(Close)了的資源。這是怎么一回事呢?讓我們來(lái)尋找答案:

根據(jù)Scope Chain的理解可以解釋,返回的內(nèi)嵌函數(shù)已經(jīng)持有了構(gòu)造它時(shí)的Scope Chain,雖然outer返回導(dǎo)致這些對(duì)象超出了作用域、生存期范圍,但JavaScript使用自動(dòng)垃圾回收來(lái)釋放對(duì)象內(nèi)存: 按照規(guī)則定期檢查,對(duì)象沒(méi)有任何引用才被釋放。因此上面的代碼能夠正確運(yùn)行。

參考:
http://www.cnblogs.com/RicCC/archive/2008/02/15/JavaScript-Object-Model-Execution-Model.html
http://www.cn-cuckoo.com/2007/08/01/understand-javascript-closures-72.html
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 义乌市| 长葛市| 平度市| 布拖县| 汝城县| 门头沟区| 都江堰市| 寿光市| 曲沃县| 德化县| 兴隆县| 睢宁县| 南江县| 长沙县| 莆田市| 兴安县| 甘南县| 牙克石市| 固始县| 西青区| 临漳县| 彭泽县| 安远县| 台北县| 阿巴嘎旗| 五寨县| 安泽县| 天峨县| 涪陵区| 武宣县| 镇赉县| 舒兰市| 犍为县| 江永县| 东港市| 通山县| 当阳市| 柏乡县| 齐齐哈尔市| 鹤壁市| 寻乌县|