閉包,看這一篇就夠了——帶你看透閉包的本質,百發百中

羊二哥發表於2019-04-22

1、概念

閉包函式:宣告在一個函式中的函式,叫做閉包函式。

閉包:內部函式總是可以訪問其所在的外部函式中宣告的引數和變數,即使在其外部函式被返回(壽命終結)了之後。

2、特點

  讓外部訪問函式內部變數成為可能;

  區域性變數會常駐在記憶體中;

  可以避免使用全域性變數,防止全域性變數汙染;

  會造成記憶體洩漏(有一塊記憶體空間被長期佔用,而不被釋放)

3、閉包的建立:­­­

閉包就是可以建立一個獨立的環境,每個閉包裡面的環境都是獨立的,互不干擾。閉包會發生記憶體洩漏,每次外部函式執行的時 候,外部函式的引用地址不同,都會重新建立一個新的地址。但凡是當前活動物件中有被內部子集引用的資料,那麼這個時候,這個資料不刪除,保留一根指標給內部活動物件。

閉包記憶體洩漏為: key = value,key 被刪除了 value 常駐記憶體中; 區域性變數閉包升級版(中間引用的變數) => 自由變數;

 

上面的都是什麼鬼,是人話麼,能看懂早就看懂了,生氣······

不過,答應我,看完例子再回看上面的概念,會理解的更!透!徹!

---------------------------------------------我是容易看懂的分界線-----------------------------------------------

4、閉包的應用場景

結論:閉包找到的是同一地址中父級函式中對應變數最終的值

最終祕訣就這一句話,每個例子請自行帶入這個結論!!!!!!!!!!!!!

/* 例子1 */

function funA(){
  var a = 10;  // funA的活動物件之中;
  return function(){   //匿名函式的活動物件;
        alert(a);
  }
}
var b = funA();
b();  //10

/* 例子2 */

function outerFn(){
  var i = 0; 
  function innerFn(){
      i++;
      console.log(i);
  }
  return innerFn;
}
var inner = outerFn();  //每次外部函式執行的時候,都會開闢一塊記憶體空間,外部函式的地址不同,都會重新建立一個新的地址
inner();
inner();
inner();
var inner2 = outerFn();
inner2();
inner2();
inner2();   //1 2 3 1 2 3

/* 例子3 */

var i = 0;
function outerFn(){
  function innnerFn(){
       i++;
       console.log(i);
  }
  return innnerFn;
}
var inner1 = outerFn();
var inner2 = outerFn();
inner1();
inner2();
inner1();
inner2();     //1 2 3 4

/* 例子4 */

function fn(){
	var a = 3;
	return function(){
		return  ++a;                                     
	}
}
alert(fn()());  //4
alert(fn()());  //4    

/* 例子5 */

function outerFn(){
var i = 0;
  function innnerFn(){
      i++;
      console.log(i);
  }
  return innnerFn;
}
var inner1 = outerFn();
var inner2 = outerFn();
inner1();
inner2();
inner1();
inner2();    //1 1 2 2

/* 例子6 */

(function() { 
  var m = 0; 
  function getM() { return m; } 
  function seta(val) { m = val; } 
  window.g = getM; 
  window.f = seta; 
})(); 
f(100);
console.info(g());   //100  閉包找到的是同一地址中父級函式中對應變數最終的值

/* 例子7 */

function a() { 
  var i = 0; 
  function b() { alert(++i); } 
  return b; 
} 
var c = a(); 
c();      //1 
c();      //2 

/* 例子8 */

function f() { 
  var count = 0; 
  return  function() { 
      count++; 
      console.info(count); 
  } 
} 
var t1 = f();
t1();     //1 
t1();     //2 
t1();     //3 

/* 例子9 */

var add = function(x) { 
  var sum = 1; 
  var tmp = function(x) { 
      sum = sum + x; 
      return tmp;    
  } 
  tmp.toString = function() { 
      return sum; 
  }
  return tmp; 
} 
alert(add(1)(2)(3));     //6

/* 例子10 */

var lis = document.getElementsByTagName("li");
for(var i=0;i<lis.length;i++){
  (function(i){
      lis[i].onclick = function(){
           console.log(i);
      };
  })(i);       //事件處理函式中閉包的寫法
}  

/* 例子11 */

function m1(){
     var x = 1;
     return function(){
          console.log(++x);
     }
}

m1()();   //2
m1()();   //2
m1()();   //2

var m2 = m1();
m2();   //2
m2();   //3
m2();   //4

/* 例子12 */

var  fn=(function(){
   var  i=10;
   function  fn(){
      console.log(++i);
   }
   return   fn;
})() 
fn();   //11
fn();   //12

/* 例子13 */

function love1(){
     var num = 223;
     var me1 = function() {
           console.log(num);
     }
     num++;
     return me1;
}
var loveme1 = love1();
loveme1();   //輸出224

/* 例子14 */

function fun(n,o) {
    console.log(o);
    return {
         fun:function(m) {
               return fun(m,n);
         }
    };
}
var a = fun(0);  //undefined
a.fun(1);  //0  
a.fun(2);  //0  
a.fun(3);  //0  
var b = fun(0).fun(1).fun(2).fun(3);   //undefined  0  1  2
var c = fun(0).fun(1);  
c.fun(2);  
c.fun(3);  //undefined  0  1  1

/* 例子15 */

function fn(){
   var arr = [];
   for(var i = 0;i < 5;i ++){
	 arr[i] = function(){
		 return i;
	 }
   }
   return arr;
}
var list = fn();
for(var i = 0,len = list.length;i < len ; i ++){
   console.log(list[i]());
}  //5 5 5 5 5

/* 例子16 */

function fn(){
  var arr = [];
  for(var i = 0;i < 5;i ++){
	arr[i] = (function(i){
		return function (){
			return i;
		};
	})(i);
  }
  return arr;
}
var list = fn();
for(var i = 0,len = list.length;i < len ; i ++){
  console.log(list[i]());
}  //0 1 2 3 4

 

相關文章