作用域/變量回收/閉包

所有變量(包括基本類型和引用類型)都存在于一個執(zhí)行環(huán)境(也稱作作用域)當中。這個變量決定了變量的生命周期,以及哪一部分代碼可以訪問其中的變量。

變量的執(zhí)行環(huán)境有助于確定應(yīng)該何時釋放內(nèi)存。

JS是一門具有自動垃圾收集機制的編程語言。離開作用域的值將被自動標記為可以回收,在垃圾收集期間被刪除。

當函數(shù)內(nèi)部定義了其它函數(shù)時,就創(chuàng)建了閉包。閉包的作用域鏈包含自己的作用域、包含函數(shù)(外部函數(shù))的作用域和全局作用域。通常函數(shù)作用域及其所有變量都會在函數(shù)執(zhí)行結(jié)束后被銷毀,但是當函數(shù)返回一個閉包時,這個函數(shù)的作用域會一直在內(nèi)存中保存到閉包不存在為止。

function f1() {
  var n = 999;
  function f2() {
    console.log(n);
  }
  return f2;
}

var result = f1();
result(); // 999

f2可以讀取f1的局部變量,要把f2作為返回值,可以在f1外部讀取它的內(nèi)部變量。

function createIncrementor(start) {
  return function () {
    return start++;
  };
}

var inc = createIncrementor(5);

inc() // 5
inc() // 6
inc() // 7

var add = (function () {
    var counter = 0;
    return function () {return counter += 1;}
})();

add() //1
add() //2
add() //3

注意: 為什么上面這段代碼沒有直接寫的 function add (){...} 而是把function賦值給了變量add呢?

我們通常會想當然的認為每次調(diào)用 add() 都會重走一遍add()中的代碼塊, 但其實不然。

注意add方法中的return, 它return的并不是1,2,3這樣的數(shù)值,而是return了一個方法,并且把這個方法賦值給了add變量。

那么在這個function自運行一遍之后,其實最后賦值給add的是return counter += 1 這段代碼。

所以后面每次調(diào)用add() 其實都是在調(diào)用return counter += 1。

再結(jié)合之前所說的, 閉包會持有父方法的局部變量并且不會隨父方法銷毀而銷毀, 所以這個counter其實就是來自于第一次function執(zhí)行時創(chuàng)建的變量。

使用閉包可以模仿塊級作用域。

閉包還可以用于在對象中創(chuàng)建私有變量。

function Person(name) {
  var _age;
  function setAge(n) {
    _age = n;
  }
  function getAge() {
    return _age;
  }

  return {
    name: name,
    getAge: getAge,
    setAge: setAge
  };
}

var p1 = Person('張三');
p1.setAge(25);
p1.getAge() // 25

創(chuàng)建閉包必須維護額外的作用域,過度使用它們可能會占用大量內(nèi)存。

最后編輯于
?著作權(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)容