閉包

整理一下對閉包的理解


閉包foo
var fn = null; //定義全局變量 fn
function foo() {
  var a = 2;
  function innerFoo() { //定義內部函數 innerFoo
    console.log(a);
  }
  fn = innerFoo; //將 innerFoo 賦值給全局變量 fn
}

foo(); // undefined
fn(); // 2

為什么要用閉包呢?

  1. 我們想要讀取其他函數內部(當前作用域之外)變量,如訪問函數 foo 內部的變量 a
  2. 當函數 foo 執行完畢后,生命周期結束,其函數的上下文失去引用,占用的內存空間很快就會被垃圾回收期釋放,閉包會阻止這一過程
  3. 盡可能少的全局變量。
console

什么是閉包呢?

當函數(內部函數)可以記住并訪問所在的作用域(全局作用域除外)時,就產生了閉包,使函數在當前作用域外執行。

在 JavaScript 中內部函數可以訪問外部函數的上下文。

在例文代碼中閉包是什么呢?

foo 是閉包(Chrome 瀏覽器認為),而不是之前一直認為的 innerFoo 。

閉包的應用

延遲函數柯里化模塊
以延遲函數為例:

function fn() {
  console.log("hello world");
}

var timer = setTimeout(fn,1000);
timer;
console_2

執行 timer 時,返回這個 setTimeout 的 ID,表明 setTimeout 函數本身已經執行完畢。一秒鐘之后,fn (保存在 setTimeout 的變量對象中)才會執行。
按理來說一秒后 setTimeout 執行結束后,fn 也就不存在了,但是事實上依舊輸出了 hello world。
這正是由于閉包。setTimeout 保留了 fn 的引用,使 fn 沒有在其執行完畢后被垃圾收集器回收。由此 setTimeout 執行結束后一秒,我們仍能使用 fn 。

帶來的問題-內存泄露

  • 閉包會使得函數中的變量都被保存在內存中,內存消耗很大,所以不能濫用閉包,否則會造成網頁的性能問題。

  • 由于IEjs 對象和DOM 對象使用不同的垃圾收集方法,因此閉包在IE中會導致內存泄露問題,也就是無法銷毀駐留在內存中的元素。

  • 解決思路:在函數之前,將不使用的局部變量全部刪除。

  • 賦值 null,解除引用

function closure(){
    var element = document.getElementById('someElement');//element用完之后一直駐留在內存中
    element.onclick = function () {
        alert('element.id');//這里用element導致內存泄露
    };
}
closure();
//解決
function closure(){
    var element = document.getElementById('someElement');
    var id = element.id; //將element.id保存在一個變量中,然后在內部函數中引用,消除對該變量的循環引用。
    element.onclick = function () {
        alert('id');
    };
    element = null;  //將element解除引用來避免內存泄露
}
  • 在外面包一層匿名自執行函數
 (function () {
  ...//閉包
        })();
//好處:不會污染全局變量,在匿名函數執行完了里面的的變量就釋放掉了

相關輸出題目

for (var i=0;i<5;i++){
  setTimeout(function(){
    console.log(i++)
  },1000);
}
// 5,6,7,8,9

for (var i=0;i<5;i++){
  setTimeout(function(){
    console.log(++i)
  },1000);
}
// 6,7,8,9,10

for (let i=0;i<5;i++){
  setTimeout(function(){
    console.log(i++)
  },1000);
}
// 0,1,2,3,4

for (var i=0;i<5;i++){
  (function(x){
    setTimeout(function(){
      console.log(x++)
    },1000);
  })(i)
}
// 0,1,2,3,4

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容