JavaScript 筆記三:作用域、閉包、內(nèi)存的管理與泄漏

都是本人理解,筆記大致概念,不詳細也并非完全正確,所以僅供參考。


作用域

ES5 中,除全局作用域外,每一個函數(shù)塊存在屬于自己的作用域,稱之為函數(shù)作用域,在其內(nèi)部聲明的變量無法被外部使用到。

但可以使用上級作用域的變量,其概念類似原型鏈,一層一層尋找,找到了就使用。

原型鏈參考筆記二:JavaScript 原型鏈的深度剖析

而全局下的變量就屬于全局作用域。

var a = 123;
window.a === a // true

ES6 中新增了一個塊級作用域,主要是給 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

閉包

簡單來說,就是一個作用域里可以調(diào)用外部作用域的變量和函數(shù),則稱之為閉包。

PS:如果一個函數(shù)訪問了它的外部變量,那么它就是一個閉包。

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 實現(xiàn)了閉包。


內(nèi)存管理(垃圾收集機制)

內(nèi)存管理的機制就是周期性執(zhí)行這一操作:找出不再使用的變量,釋放其空間。

主要有以下兩種方式。

  • 標記清除
  • 引用計數(shù)

標記清除

標記清除是JavaScript最常用的內(nèi)存管理機制,即當變量進入環(huán)境時,則標記這個變量為進入,而當變量離開環(huán)境時,則將其標記為離開。

function add(n){
  var sum += n;    // 進入
  return sum;      // 離開
}
add(1); // 1

變量的定義和賦空值,也會出發(fā)標記清除:

var user = {
  name: 'jack',
  age: 20
};  // 在作用域定義變量,標記變量為進入

// some code ...

user = null;    //最后定義為null,標記變量為離開,釋放內(nèi)存

引用計數(shù)

引用計數(shù)是不太常見的內(nèi)存管理機制,顧名思義,引用計數(shù)會跟蹤記錄每個值被引用的次數(shù),若是為0則清除。

var user = {
  name: 'jack',
  age: 20
};  // 引用次數(shù) + 1

// some code ...

user = null;    // 最后定義為null,引用計數(shù) -1 ,為0清除

但引用計數(shù)會因為變量相互引用,造成內(nèi)存計數(shù)永不為0,故而雖然已經(jīng)執(zhí)行完了代碼,但是還是不會清除變量。

function a(){
  var b = {};
  var c = {};
  b.test = c;
  c.test = b;
}
a(); // 雖然 a 已經(jīng)執(zhí)行完,但是還是不會清楚 b 和 c 。

總結(jié)

雖然大多瀏覽器上JavaScript的內(nèi)存管理機制是標記清除,但是在 IE 瀏覽器(又是它)中,某些對象的內(nèi)存管理機制是引用計數(shù),如IE的 DOM和BOM,(統(tǒng)稱為COM對象),所以在寫代碼時要避免相互引用。


內(nèi)存泄漏

首先,內(nèi)存泄漏并不是不合理的,如閉包就會造成內(nèi)存泄漏,但是大家還是在使用閉包的方式寫函數(shù),所以存在即合理,需要做的,是在合理使用的情況下把不合理的去掉。

常見的造成內(nèi)存泄漏的情況:

  • 定義全局對象
  • 閉包
  • dom清空或刪除時,事件未清除
  • 相互引用

由上可知,基本解決方案就是:

  • 不要輕易定義全局變量
  • 如果有必要,盡量減少閉包函數(shù)。
  • 刪除dom時,清除dom以及其子節(jié)點綁定的函數(shù)
  • 不要相互引用,即使要相互引用,最后請加一個 a = null 切斷聯(lián)系

PS:不是很全面,要深度研究請網(wǎng)上沖浪,這里僅做一些參考。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容