都是本人理解肌索,筆記大致概念蕉拢,不詳細(xì)也并非完全正確,所以僅供參考诚亚。
作用域
ES5 中晕换,除全局作用域外,每一個(gè)函數(shù)塊存在屬于自己的作用域站宗,稱之為函數(shù)作用域闸准,在其內(nèi)部聲明的變量無法被外部使用到。
但可以使用上級(jí)作用域的變量梢灭,其概念類似原型鏈夷家,一層一層尋找,找到了就使用敏释。
原型鏈參考筆記二:JavaScript 原型鏈的深度剖析
而全局下的變量就屬于全局作用域库快。
var a = 123;
window.a === a // true
ES6 中新增了一個(gè)塊級(jí)作用域,主要是給 let 和 const 使用钥顽,簡單來說就是义屏,任何被函數(shù) {} 包裹的區(qū)域,如:
if(1){
let a = 1;
const b = 2;
}
console.log(a); // a is not defined
console.log(b); // b is not defined
閉包
簡單來說,就是一個(gè)作用域里可以調(diào)用外部作用域的變量和函數(shù)闽铐,則稱之為閉包蝶怔。
PS:如果一個(gè)函數(shù)訪問了它的外部變量,那么它就是一個(gè)閉包兄墅。
function a(x) {
var age = x;
return function (name) {
console.log(name, age);
age++;
}
}
var age = 10;
var b = a(age);
b('jack'); // jack 10
b('jack'); // jack 11
b('jack'); // jack 12
所以可以說踢星,a 實(shí)現(xiàn)了閉包。
內(nèi)存管理(垃圾收集機(jī)制)
內(nèi)存管理的機(jī)制就是周期性執(zhí)行這一操作:找出不再使用的變量察迟,釋放其空間斩狱。
主要有以下兩種方式。
- 標(biāo)記清除
- 引用計(jì)數(shù)
標(biāo)記清除
標(biāo)記清除是JavaScript最常用的內(nèi)存管理機(jī)制扎瓶,即當(dāng)變量進(jìn)入環(huán)境時(shí)所踊,則標(biāo)記這個(gè)變量為進(jìn)入,而當(dāng)變量離開環(huán)境時(shí)概荷,則將其標(biāo)記為離開秕岛。
function add(n){
var sum += n; // 進(jìn)入
return sum; // 離開
}
add(1); // 1
變量的定義和賦空值,也會(huì)出發(fā)標(biāo)記清除:
var user = {
name: 'jack',
age: 20
}; // 在作用域定義變量误证,標(biāo)記變量為進(jìn)入
// some code ...
user = null; //最后定義為null继薛,標(biāo)記變量為離開,釋放內(nèi)存
引用計(jì)數(shù)
引用計(jì)數(shù)是不太常見的內(nèi)存管理機(jī)制愈捅,顧名思義遏考,引用計(jì)數(shù)會(huì)跟蹤記錄每個(gè)值被引用的次數(shù),若是為0則清除蓝谨。
var user = {
name: 'jack',
age: 20
}; // 引用次數(shù) + 1
// some code ...
user = null; // 最后定義為null灌具,引用計(jì)數(shù) -1 ,為0清除
但引用計(jì)數(shù)會(huì)因?yàn)樽兞肯嗷ヒ闷┪祝斐蓛?nèi)存計(jì)數(shù)永不為0咖楣,故而雖然已經(jīng)執(zhí)行完了代碼,但是還是不會(huì)清除變量芦昔。
function a(){
var b = {};
var c = {};
b.test = c;
c.test = b;
}
a(); // 雖然 a 已經(jīng)執(zhí)行完诱贿,但是還是不會(huì)清楚 b 和 c 。
總結(jié)
雖然大多瀏覽器上JavaScript的內(nèi)存管理機(jī)制是標(biāo)記清除咕缎,但是在 IE 瀏覽器(又是它)中珠十,某些對象的內(nèi)存管理機(jī)制是引用計(jì)數(shù),如IE的 DOM和BOM凭豪,(統(tǒng)稱為COM對象)焙蹭,所以在寫代碼時(shí)要避免相互引用。
內(nèi)存泄漏
首先墅诡,內(nèi)存泄漏并不是不合理的壳嚎,如閉包就會(huì)造成內(nèi)存泄漏桐智,但是大家還是在使用閉包的方式寫函數(shù),所以存在即合理烟馅,需要做的说庭,是在合理使用的情況下把不合理的去掉。
常見的造成內(nèi)存泄漏的情況:
- 定義全局對象
- 閉包
- dom清空或刪除時(shí)郑趁,事件未清除
- 相互引用
由上可知刊驴,基本解決方案就是:
- 不要輕易定義全局變量
- 如果有必要,盡量減少閉包函數(shù)寡润。
- 刪除dom時(shí)捆憎,清除dom以及其子節(jié)點(diǎn)綁定的函數(shù)
- 不要相互引用,即使要相互引用梭纹,最后請加一個(gè) a = null 切斷聯(lián)系
PS:不是很全面躲惰,要深度研究請網(wǎng)上沖浪,這里僅做一些參考变抽。