困擾javascript初學者的閉包

dunne21發表於2021-09-09

一,理解閉包就先要理解作用域

作用域scope 在js中作用域scope是由函式劃分的,所有屬於全域性作用域的變數都是window物件的屬性(property);

//隱式的宣告全域性變數
function test(){
  foo = "test";
}
function A() {
  var num = 2;
  function B(){
    console.log(num);
    }
}
//B函式可以訪問A函式,A函式不能訪問A函式里定義的變數,那麼B函式能訪問A函式里定義的變數。
//那麼可以將B函式作為返回值,然後提供給外部(作為介面),那麼外部就可以訪問A函式里的變數了.
//鏈式作用域chain scope:子物件一級一級向父級物件尋找變數

二,閉包 closure:內層的函式可以引用他外層函式內的變數,即使外層
的執行已經終止.

//閉包的典型案例,實現訪問函式內部的變數,
 function people () {
  var name = "maoguotao";
  function getName(){
     console.log(name);
   }
  return getName;
}
  var person = people();
  person();

函式getName就是這個people函式的對外提供的介面能夠訪問到內部定義的區域性變數name;因此getName函式和變數name組成的環境就稱之為閉包.

閉包的兩個特點:1,可以訪問函式內部的變數。2,這些變數的值始終是儲存在記憶體中。

1,可以訪問函式內部的變數。

function delayAlert(msg,time){
    setTimeout(function(){
     alert(msg);
   },time);
}
delayAlert("welcome",2000);
//用閉包實現函式curry化
//數字求和函式的函式生成器
 function addGenerator( num ){
 //返回一個簡單的函式.求兩個數字的和,其中一個來自函式生成器
   return function (toAdd){
      return num + toAdd;
     }
  };
var addFive =addGenerator(5);
alert(addFive(4) == 9);
//建構函式里的this指的是建構函式的例項物件
function A(){
 var name = "maoguotao";
 this.getName = function(){
    console.log(name);
  }
}
var a = new A();
a.getName();
//建構函式里的this指的是建構函式的例項物件
function B(){
   var name = "MGT360124";
   this.getName = function (){
   console.log(name);
  }
}
var b = new B();
b.getName();

2,這些變數的值始終是儲存在記憶體中

function A(){
    var name = "maoguotao";
    addName = function (){
    name = name+"12";
   }
  function getName(){
   console.log(name+"34"); 
  }
return getName;
}
var  a =  A();
a();
addName();
a();

a函式執行了兩次,也就是閉包getName函式執行了兩次,實際上區域性變數name是儲存在記憶體中的,並沒有在第一次的a()呼叫完之後清除,因為A函式是getName閉包函式的父函式,而getName函式被賦給a全域性變數,使得getName函式始終在記憶體中,而getName函式依賴於A函式,所以A函式也是在記憶體中,不會在呼叫結束後清除。
閉包的缺點:

1,閉包使得函式中的變數儲存在記憶體中,對記憶體消耗很大,不能濫用.會造成網頁的效能問題,在IE中可能導致記憶體的洩露,解決辦法就是在退出函式之前將不使用的區域性變數全部刪除
2,閉包會在父函式外部,改變父函式的內部變數的值.因此,把父函式當作object物件使用,把閉包當作他的公用方法(public Method);把內部變數當作他的私有屬性(private value)

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/1600/viewspace-2799482/,如需轉載,請註明出處,否則將追究法律責任。

相關文章