中文字幕免费精品_亚洲视频自拍_亚洲综合国产激情另类一区_色综合咪咪久久

JS閉包、作用域鏈、垃圾回收、內(nèi)存泄露相關(guān)知識(shí)小結(jié)
來源:易賢網(wǎng) 閱讀:1464 次 日期:2016-06-29 16:12:32
溫馨提示:易賢網(wǎng)小編為您整理了“JS閉包、作用域鏈、垃圾回收、內(nèi)存泄露相關(guān)知識(shí)小結(jié)”,方便廣大網(wǎng)友查閱!

閉包是指有權(quán)訪問另一個(gè)函數(shù)作用域中變量的函數(shù)。接下來通過本文給大家介紹JS閉包作用域鏈等相關(guān)知識(shí)小結(jié)(垃圾回收內(nèi)存泄露)的相關(guān)知識(shí),感興趣的朋友一起學(xué)習(xí)吧

補(bǔ)充:

閉包(closure)是Javascript語(yǔ)言的一個(gè)難點(diǎn),也是它的特色,很多高級(jí)應(yīng)用都要依靠閉包實(shí)現(xiàn)。

閉包的特性

閉包有三個(gè)特性:

1.函數(shù)嵌套函數(shù)

2.函數(shù)內(nèi)部可以引用外部的參數(shù)和變量

3.參數(shù)和變量不會(huì)被垃圾回收機(jī)制回收

閉包的定義及其優(yōu)缺點(diǎn)

閉包 是指有權(quán)訪問另一個(gè)函數(shù)作用域中的變量的函數(shù),創(chuàng)建閉包的最常見的方式就是在一個(gè)函數(shù)內(nèi)創(chuàng)建另一個(gè)函數(shù),通過另一個(gè)函數(shù)訪問這個(gè)函數(shù)的局部變量

閉包的缺點(diǎn)就是常駐內(nèi)存,會(huì)增大內(nèi)存使用量,使用不當(dāng)很容易造成內(nèi)存泄露。

閉包是javascript語(yǔ)言的一大特點(diǎn),主要應(yīng)用閉包場(chǎng)合主要是為了:設(shè)計(jì)私有的方法和變量。

一般函數(shù)執(zhí)行完畢后,局部活動(dòng)對(duì)象就被銷毀,內(nèi)存中僅僅保存全局作用域。但閉包的情況不同!

圍著主題展開話題

1. 閉包的定義?

來看一些關(guān)于閉包的定義:

1.閉包是指有權(quán)訪問另一個(gè)函數(shù)作用域中變量的函數(shù)

2.函數(shù)對(duì)象可以通過作用域鏈相關(guān)聯(lián)起來,函數(shù)體內(nèi)部的變量都可以保存在函數(shù)作用域內(nèi),這種特性稱為 ‘閉包' 。

3.內(nèi)部函數(shù)可以訪問定義它們的外部函數(shù)的參數(shù)和變量(除了this和arguments)。

大家想系統(tǒng)的學(xué)習(xí)js閉包的概念可以參考腳本之家網(wǎng)站的js電子書欄目學(xué)習(xí)吧。

來個(gè)定義總結(jié)

1.可以訪問外部函數(shù)作用域中變量的函數(shù)

2.被內(nèi)部函數(shù)訪問的外部函數(shù)的變量可以保存在外部函數(shù)作用域內(nèi)而不被回收---這是核心,后面我們遇到閉包都要想到,我們要重點(diǎn)關(guān)注被閉包引用的這個(gè)變量。

來創(chuàng)建個(gè)簡(jiǎn)單的閉包

var sayName = function(){

var name = 'jozo';

return function(){

alert(name);

}

};

var say = sayName();

say();

來解讀后面兩個(gè)語(yǔ)句:

•var say = sayName() :返回了一個(gè)匿名的內(nèi)部函數(shù)保存在變量say中,并且引用了外部函數(shù)的變量name,由于垃圾回收機(jī)制,sayName函數(shù)執(zhí)行完畢后,變量name并沒有被銷毀。

•say() :執(zhí)行返回的內(nèi)部函數(shù),依然能訪問變量name,輸出 'jozo' .

2. 閉包中的作用域鏈

理解作用域鏈對(duì)理解閉包也很有幫助。

變量在作用域中的查找方式應(yīng)該都很熟悉了,其實(shí)這就是順著作用域鏈往上查找的。

當(dāng)函數(shù)被調(diào)用時(shí):

1.先創(chuàng)建一個(gè)執(zhí)行環(huán)境(execution context),及相應(yīng)的作用域鏈;

2.將arguments和其他命名參數(shù)的值添加到函數(shù)的活動(dòng)對(duì)象(activation object)

作用域鏈:當(dāng)前函數(shù)的活動(dòng)對(duì)象優(yōu)先級(jí)最高,外部函數(shù)的活動(dòng)對(duì)象次之,外部函數(shù)的外部函數(shù)的活動(dòng)對(duì)象依次遞減,直至作用域鏈的末端--全局作用域。優(yōu)先級(jí)就是變量查找的先后順序;

先來看個(gè)普通的作用域鏈:

function sayName(name){

return name;

}

var say = sayName('jozo');

這段代碼包含兩個(gè)作用域:a.全局作用域;b.sayName函數(shù)的作用域,也就是只有兩個(gè)變量對(duì)象,當(dāng)執(zhí)行到對(duì)應(yīng)的執(zhí)行環(huán)境時(shí),該變量對(duì)象會(huì)成為活動(dòng)對(duì)象,并被推入到執(zhí)行環(huán)境作用域鏈的前端,也就是成為優(yōu)先級(jí)最高的那個(gè)。 看圖說話:

這圖在JS高級(jí)程序設(shè)計(jì)書上也有,我重新繪了遍。

在創(chuàng)建sayName()函數(shù)時(shí),會(huì)創(chuàng)建一個(gè)預(yù)先包含變量對(duì)象的作用域鏈,也就是圖中索引為1的作用域鏈,并且被保存到內(nèi)部的[[Scope]]屬性中,當(dāng)調(diào)用sayName()函數(shù)的時(shí)候,會(huì)創(chuàng)建一個(gè)執(zhí)行環(huán)境,然后通過復(fù)制函數(shù)的[[Scope]]屬性中的對(duì)象構(gòu)建起作用域鏈,此后,又有一個(gè)活動(dòng)對(duì)象(圖中索引為0)被創(chuàng)建,并被推入執(zhí)行環(huán)境作用域鏈的前端。

一般來說,當(dāng)函數(shù)執(zhí)行完畢后,局部活動(dòng)對(duì)象就會(huì)被銷毀,內(nèi)存中僅保存全局作用域。但是,閉包的情況又有所不同 :

再來看看看閉包的作用域鏈:

function sayName(name){

return function(){

return name;

}

}

var say = sayName('jozo');

這個(gè)閉包實(shí)例比上一個(gè)例子多了一個(gè)匿名函數(shù)的作用域:

在匿名函數(shù)從sayName()函數(shù)中被返回后,它的作用域鏈被初始化為包含sayName()函數(shù)的活動(dòng)對(duì)象和全局變量對(duì)象。這樣,匿名函數(shù)就可以訪問在sayName()中定義的所有變量和參數(shù),更為重要的是,sayName()函數(shù)在執(zhí)行完畢后,其活動(dòng)對(duì)象也不會(huì)被銷毀,因?yàn)槟涿瘮?shù)的作用域鏈依然在引用這個(gè)活動(dòng)對(duì)象,換句話說,sayName()函數(shù)執(zhí)行完后,其執(zhí)行環(huán)境的作用域鏈會(huì)被銷毀,但他的活動(dòng)對(duì)象會(huì)留在內(nèi)存中,知道匿名函數(shù)會(huì)銷毀。這個(gè)也是后面要講到的內(nèi)存泄露的問題。

作用域鏈問題不寫那么多了,寫書上的東西也很累 o(╯□╰)o

3. 閉包的實(shí)例

實(shí)例1:實(shí)現(xiàn)累加

// 方式1

var a = 0;

var add = function(){

a++;

console.log(a)

}

add();

add();

//方式2 :閉包

var add = (function(){

var a = 0;

return function(){

a++;

console.log(a);

}

})();

console.log(a); //undefined

add();

add();

相比之下方式2更加優(yōu)雅,也減少全局變量,將變量私有化

實(shí)例2 :給每個(gè)li添加點(diǎn)擊事件

var oli = document.getElementsByTagName('li');

var i;

for(i = 0;i < 5;i++){

oli[i].onclick = function(){

alert(i);

}

}

console.log(i); // 5

//執(zhí)行匿名函數(shù)

(function(){

alert(i); //5

}());

上面是一個(gè)經(jīng)典的例子,我們都知道執(zhí)行結(jié)果是都彈出5,也知道可以用閉包解決這個(gè)問題,但是我剛開始始終不能明白為什么每次彈出都是5,為什么閉包可以解決這問題。后來捋一捋還是把它弄清晰了:

a. 先來分析沒用閉包前的情況:for循環(huán)中,我們給每個(gè)li點(diǎn)擊事件綁定了一個(gè)匿名函數(shù),匿名函數(shù)中返回了變量i的值,當(dāng)循環(huán)結(jié)束后,變量i的值變?yōu)?,此時(shí)我們?cè)偃c(diǎn)擊每個(gè)li,也就是執(zhí)行相應(yīng)的匿名函數(shù)(看上面的代碼),這是變量i已經(jīng)是5了,所以每個(gè)點(diǎn)擊彈出5. 因?yàn)檫@里返回的每個(gè)匿名函數(shù)都是引用了同一個(gè)變量i,如果我們新建一個(gè)變量保存循環(huán)執(zhí)行時(shí)當(dāng)前的i的值,然后再讓匿名函數(shù)應(yīng)用這個(gè)變量,最后再返回這個(gè)匿名函數(shù),這樣就可以達(dá)到我們的目的了,這就是運(yùn)用閉包來實(shí)現(xiàn)的!

b. 再來分析下運(yùn)用閉包時(shí)的情況:

var oli = document.getElementsByTagName('li');

var i;

for(i = 0;i < 5;i++){

oli[i].onclick = (function(num){

var a = num; // 為了說明問題

return function(){

alert(a);

}

})(i)

}

console.log(i); // 5

這里for循環(huán)執(zhí)行時(shí),給點(diǎn)擊事件綁定的匿名函數(shù)傳遞i后立即執(zhí)行返回一個(gè)內(nèi)部的匿名函數(shù),因?yàn)閰?shù)是按值傳遞的,所以此時(shí)形參num保存的就是當(dāng)前i的值,然后賦值給局部變量 a,然后這個(gè)內(nèi)部的匿名函數(shù)一直保存著a的引用,也就是一直保存著當(dāng)前i的值。 所以循環(huán)執(zhí)行完畢后點(diǎn)擊每個(gè)li,返回的匿名函數(shù)執(zhí)行彈出各自保存的 a 的引用的值。

4. 閉包的運(yùn)用

我們來看看閉包的用途。事實(shí)上,通過使用閉包,我們可以做很多事情。比如模擬面向?qū)ο蟮拇a風(fēng)格;更優(yōu)雅,更簡(jiǎn)潔的表達(dá)出代碼;在某些方面提升代碼的執(zhí)行效率。

1. 匿名自執(zhí)行函數(shù)

我們?cè)趯?shí)際情況下經(jīng)常遇到這樣一種情況,即有的函數(shù)只需要執(zhí)行一次,其內(nèi)部變量無需維護(hù),比如UI的初始化,那么我們可以使用閉包:

//將全部li字體變?yōu)榧t色

(function(){

var els = document.getElementsByTagName('li');

for(var i = 0,lng = els.length;i < lng;i++){

els[i].style.color = 'red';

}

})();

我們創(chuàng)建了一個(gè)匿名的函數(shù),并立即執(zhí)行它,由于外部無法引用它內(nèi)部的變量,因此els,i,lng這些局部變量在執(zhí)行完后很快就會(huì)被釋放,節(jié)省內(nèi)存!

關(guān)鍵是這種機(jī)制不會(huì)污染全局對(duì)象。

2. 實(shí)現(xiàn)封裝/模塊化代碼

var person= function(){

//變量作用域?yàn)楹瘮?shù)內(nèi)部,外部無法訪問

var name = "default";

return {

getName : function(){

return name;

},

setName : function(newName){

name = newName;

}

}

}();

console.log(person.name);//直接訪問,結(jié)果為undefined

console.log(person.getName()); //default

person.setName("jozo");

console.log(person.getName()); //jozo

3. 實(shí)現(xiàn)面向?qū)ο笾械膶?duì)象

這樣不同的對(duì)象(類的實(shí)例)擁有獨(dú)立的成員及狀態(tài),互不干涉。雖然JavaScript中沒有類這樣的機(jī)制,但是通過使用閉包,我們可以模擬出這樣的機(jī)制。還是以上邊的例子來講:

function Person(){

var name = "default";

return {

getName : function(){

return name;

},

setName : function(newName){

name = newName;

}

}

};

var person1= Person();

print(person1.getName());

john.setName("person1");

print(person1.getName()); // person1

var person2= Person();

print(person2.getName());

jack.setName("erson2");

print(erson2.getName()); //person2

Person的兩個(gè)實(shí)例person1 和 person2 互不干擾!因?yàn)檫@兩個(gè)實(shí)例對(duì)name這個(gè)成員的訪問是獨(dú)立的 。

5. 內(nèi)存泄露及解決方案

垃圾回收機(jī)制

說到內(nèi)存管理,自然離不開JS中的垃圾回收機(jī)制,有兩種策略來實(shí)現(xiàn)垃圾回收:標(biāo)記清除 和 引用計(jì)數(shù);

標(biāo)記清除:垃圾收集器在運(yùn)行的時(shí)候會(huì)給存儲(chǔ)在內(nèi)存中的所有變量都加上標(biāo)記,然后,它會(huì)去掉環(huán)境中的變量的標(biāo)記和被環(huán)境中的變量引用的變量的標(biāo)記,此后,如果變量再被標(biāo)記則表示此變量準(zhǔn)備被刪除。 2008年為止,IE,F(xiàn)irefox,opera,chrome,Safari的javascript都用使用了該方式;

引用計(jì)數(shù):跟蹤記錄每個(gè)值被引用的次數(shù),當(dāng)聲明一個(gè)變量并將一個(gè)引用類型的值賦給該變量時(shí),這個(gè)值的引用次數(shù)就是1,如果這個(gè)值再被賦值給另一個(gè)變量,則引用次數(shù)加1。相反,如果一個(gè)變量脫離了該值的引用,則該值引用次數(shù)減1,當(dāng)次數(shù)為0時(shí),就會(huì)等待垃圾收集器的回收。

這個(gè)方式存在一個(gè)比較大的問題就是循環(huán)引用,就是說A對(duì)象包含一個(gè)指向B的指針,對(duì)象B也包含一個(gè)指向A的引用。 這就可能造成大量?jī)?nèi)存得不到回收(內(nèi)存泄露),因?yàn)樗鼈兊囊么螖?shù)永遠(yuǎn)不可能是 0 。早期的IE版本里(ie4-ie6)采用是計(jì)數(shù)的垃圾回收機(jī)制,閉包導(dǎo)致內(nèi)存泄露的一個(gè)原因就是這個(gè)算法的一個(gè)缺陷。

我們知道,IE中有一部分對(duì)象并不是原生額javascript對(duì)象,例如,BOM和DOM中的對(duì)象就是以COM對(duì)象的形式實(shí)現(xiàn)的,而COM對(duì)象的垃圾回收機(jī)制采用的就是引用計(jì)數(shù)。因此,雖然IE的javascript引擎采用的是標(biāo)記清除策略,但是訪問COM對(duì)象依然是基于引用計(jì)數(shù)的,因此只要在IE中設(shè)計(jì)COM對(duì)象就會(huì)存在循環(huán)引用的問題!

舉個(gè)栗子:

window.onload = function(){

var el = document.getElementById("id");

el.onclick = function(){

alert(el.id);

}

}

這段代碼為什么會(huì)造成內(nèi)存泄露?

el.onclick= function () {

alert(el.id);

};

執(zhí)行這段代碼的時(shí)候,將匿名函數(shù)對(duì)象賦值給el的onclick屬性;然后匿名函數(shù)內(nèi)部又引用了el對(duì)象,存在循環(huán)引用,所以不能被回收;

解決方法:

window.onload = function(){

var el = document.getElementById("id");

var id = el.id; //解除循環(huán)引用

el.onclick = function(){

alert(id);

}

el = null; // 將閉包引用的外部函數(shù)中活動(dòng)對(duì)象清除

}

以上所述是小編給大家介紹的JS閉包作用域鏈垃圾回收內(nèi)存泄露相關(guān)知識(shí)小結(jié),希望對(duì)大家有所幫助!

更多信息請(qǐng)查看網(wǎng)絡(luò)編程
由于各方面情況的不斷調(diào)整與變化,易賢網(wǎng)提供的所有考試信息和咨詢回復(fù)僅供參考,敬請(qǐng)考生以權(quán)威部門公布的正式信息和咨詢?yōu)闇?zhǔn)!

2026上岸·考公考編培訓(xùn)報(bào)班

  • 報(bào)班類型
  • 姓名
  • 手機(jī)號(hào)
  • 驗(yàn)證碼
關(guān)于我們 | 聯(lián)系我們 | 人才招聘 | 網(wǎng)站聲明 | 網(wǎng)站幫助 | 非正式的簡(jiǎn)要咨詢 | 簡(jiǎn)要咨詢須知 | 新媒體/短視頻平臺(tái) | 手機(jī)站點(diǎn) | 投訴建議
工業(yè)和信息化部備案號(hào):滇ICP備2023014141號(hào)-1 云南省教育廳備案號(hào):云教ICP備0901021 滇公網(wǎng)安備53010202001879號(hào) 人力資源服務(wù)許可證:(云)人服證字(2023)第0102001523號(hào)
云南網(wǎng)警備案專用圖標(biāo)
聯(lián)系電話:0871-65099533/13759567129 獲取招聘考試信息及咨詢關(guān)注公眾號(hào):hfpxwx
咨詢QQ:1093837350(9:00—18:00)版權(quán)所有:易賢網(wǎng)
云南網(wǎng)警報(bào)警專用圖標(biāo)
中文字幕免费精品_亚洲视频自拍_亚洲综合国产激情另类一区_色综合咪咪久久
国产亚洲在线| 久久久精品动漫| 亚洲素人一区二区| 免费观看在线综合色| 国产精品女主播| 午夜伦理片一区| 国产区日韩欧美| 欧美在线观看视频一区二区| 国产伦精品一区二区三区高清| 欧美亚洲综合久久| 亚洲第一区色| 久久久7777| 夜夜爽www精品| 国产一区二区三区黄视频| 久久米奇亚洲| 亚洲一区二区三区四区视频 | 国产嫩草影院久久久久| 午夜精品亚洲一区二区三区嫩草| 国产亚洲欧美在线| 欧美理论视频| 快射av在线播放一区| 99综合视频| 91久久黄色| 国产精品羞羞答答xxdd| 欧美丰满高潮xxxx喷水动漫| 亚洲一区二区三区高清不卡| 1024成人| 亚洲国产一区二区在线| 国产精品婷婷| 国产精品mm| 欧美日韩国产综合一区二区| 美女在线一区二区| 久久久综合网站| 久久久999精品视频| 亚洲欧美电影在线观看| 99精品国产在热久久| 亚洲日本欧美| 91久久精品美女| 99国产精品久久久久久久久久 | 91久久精品久久国产性色也91| 国产丝袜一区二区| 久久免费黄色| 久久精品成人一区二区三区| 欧美日韩1区2区| 亚洲性视频网址| 在线播放国产一区中文字幕剧情欧美| 欧美日韩99| 你懂的国产精品| 久久久高清一区二区三区| 亚洲午夜在线视频| 亚洲狠狠婷婷| 激情久久中文字幕| 国产日韩欧美亚洲| 欧美日韩免费高清| 欧美精品v日韩精品v国产精品| 久久久久国色av免费观看性色| 亚洲欧美日韩精品久久久| 日韩视频在线你懂得| 在线观看中文字幕不卡| 狠狠爱www人成狠狠爱综合网| 国产精品亚洲激情| 国产伦理一区| 国产精品日韩二区| 国产精品久久久久久五月尺| 欧美性猛交99久久久久99按摩| 欧美视频1区| 欧美色精品在线视频| 欧美日韩一区二区免费在线观看| 欧美日韩大陆在线| 欧美日韩视频在线一区二区 | 亚洲人成久久| 亚洲国产清纯| 国产自产在线视频一区| 国产精品影音先锋| 国产欧美91| 国产女精品视频网站免费| 国产精品亚洲人在线观看| 国产美女诱惑一区二区| 国产日韩精品一区二区三区| 国产一区二区三区在线观看视频 | 99精品国产在热久久婷婷| 亚洲人成网站色ww在线| 亚洲精品一区中文| 99视频在线精品国自产拍免费观看 | 91久久精品国产91久久| 亚洲免费高清| 亚洲一区二区在线观看视频| 午夜视频在线观看一区二区三区| 欧美在线免费看| 美女在线一区二区| 欧美日本一区二区视频在线观看| 国产精品国产成人国产三级| 国产亚洲一级高清| 亚洲电影免费观看高清完整版| 欧美日韩成人在线视频| 国产精品电影网站| 国产欧美欧洲在线观看| 1024日韩| 亚洲影院免费| 久久九九久久九九| 欧美va天堂在线| 欧美精彩视频一区二区三区| 国产精品久线观看视频| 国内外成人在线| 亚洲国产欧美一区| 国产精品久久二区| 国产日韩精品一区二区浪潮av| 亚洲理伦电影| 欧美在线视频日韩| 欧美连裤袜在线视频| 国产精品xxxxx| 亚洲成人在线| 一区二区三区久久久| 久久久国产午夜精品| 欧美黑人多人双交| 国产精品欧美风情| 亚洲国产女人aaa毛片在线| 国产精品99久久久久久白浆小说| 久久久久久精| 国产精品高精视频免费| 91久久久久久久久| 欧美一区二区高清| 国产精品女主播| av成人毛片| 91久久精品一区二区三区| 亚洲欧美日韩一区在线| 国产午夜精品一区二区三区欧美 | 在线视频亚洲| 在线观看国产精品淫| 在线免费观看视频一区| 亚洲精华国产欧美| 欧美一区二区高清| 欧美欧美天天天天操| 国产精品一区二区久激情瑜伽| 欧美成人免费观看| 亚洲特黄一级片| 国产精品久久久久9999高清| 亚洲手机成人高清视频| 亚洲影院在线| 欧美福利视频网站| 国产主播一区二区三区| 一区二区三区www| 欧美福利精品| 亚洲国产一二三| 久久精品综合网| 国产精品网站在线| 欧美一级大片在线免费观看| 国产精品激情偷乱一区二区∴| 亚洲国产婷婷综合在线精品| 国产精品无码专区在线观看| 久久精品国产成人| 在线看片日韩| 午夜视频久久久久久| 国产精品国产a| 一本一本久久a久久精品综合麻豆 一本一本久久a久久精品牛牛影视 | 国产精品久久久久77777| 国产欧美日韩综合一区在线观看 | 国产精品红桃| 亚洲精品精选| 欧美/亚洲一区| 在线精品国产成人综合| 国产欧美日韩综合| 亚洲综合色自拍一区| 欧美久久电影| 亚洲欧洲日本在线| 欧美亚洲视频在线观看| 国产欧美日韩在线播放| 亚洲一区二区三区四区视频| 欧美人与性动交cc0o| 亚洲高清色综合| 欧美理论在线播放| 亚洲欧美日韩国产中文| 国产欧美一区二区三区国产幕精品 | 国产综合久久久久久鬼色| 一本到高清视频免费精品| 国产精品婷婷午夜在线观看| 欧美国产一区在线| 欧美人与性动交cc0o| 日韩五码在线| 亚洲免费黄色| 久久精品91| 亚洲国产黄色| 亚洲欧美日韩国产一区| 国内偷自视频区视频综合| 每日更新成人在线视频| 日韩一区二区高清| 韩国视频理论视频久久| 欧美日韩三级| 久久精品国产欧美亚洲人人爽| 欧美日韩一区二区在线观看| 欧美a一区二区| 国产一区观看| 亚洲天堂男人| 亚洲国产精品精华液2区45| 国产在线精品一区二区中文| 欧美午夜视频| 欧美三级资源在线| 亚洲伊人第一页| 亚洲一区二区少妇| 欧美在线免费视屏|