1. 程式人生 > >JS:閉包

JS:閉包

也會 () 因此 cti ref return style not 導致

一、變量的作用域

要理解js的閉包,首先要了解js的變量作用域;

(1)js的變量有兩種:全局變量,局部變量;

js的局部變量只會在函數內部通過var聲明產生,不是通過var聲明的變量也會被當成局部變量

    var a = ‘a‘;
    function myFunc() {
      var b = ‘b‘;
      c = ‘c‘;
    }
    myFunc();
    console.log(a); // output: a
    console.log(c); // output: c
    console.log(b); // output: Uncaught ReferenceError: b is not defined

上面結果:a, c都能在全局訪問,都是全局變量, b不能再全局訪問,所以是局部變量。c雖然定義在內部,但是由於沒有通過var時聲明,所以是全局變量。

(2)變量的作用域

看下面的例子:

    var a = ‘a‘;
    function myFunc() {
      var b = ‘b‘;
      console.log(‘inner func:‘, a); // a
      console.log(‘inner func:‘, b); // b
    }
    myFunc();
    console.log(a); // output: a
    console.log(b); //
output: Uncaught ReferenceError: b is not defined

從上面的例子可以看出,函數內部可以讀取函數外部的變量,而函數外部不可以讀取函數內部的變量。

二、閉包

某些情況下,需要在函數外部訪問函數內部的變量,正常情況是辦不到的。但是我們可以想個辦法:在函數內部再定義一個函數,然後再把該函數作為返回值返回,我們就可以實現在函數的外部,讀取函數內部的變量了。而作為返回值的這個函數就是閉包。

function f1() {

   var n = 999;
    function f2() {
      console.log(
++n) } return f2; }
f2就是閉包,可以讓外部訪問內部函數的變量n。 有些人會有疑問,在f1中直接返回n不也可以讓外部訪問內部函數的變量了嗎?就像下面這樣:
    function f1() {
      var n = 999;
      return ++n;
    }
    var result1 = f1(); // 1000
    var result2 = f1(); // 1000
上面雖然能訪問變量,但是n在函數執行完之後就被銷毀了,沒有被保存下來。但是用下面的這個方法,雖然外部函數在執行完之後被銷毀了, 但是n就被保存下來了:
function f1() {

  var n = 999;
  function f2() {
    return ++n;
  }
  return f2;
}

var result = f1();
result(); // 1000
result(); // 1001
result(); // 1002

因此閉包有兩個用處:(1)可以使函數外部讀取函數內部的變量; (2)讓函數內部的變量始終保存在內存中。

因為閉包會使函數中的變量都被保存在內存中,內存消耗很大,所以不能濫用閉包,否則會造成網頁的性能問題,在IE中可能導致內存泄露。解決放法是:在退出之前, 將不使用的局部變量全部刪除;

JS:閉包