講解JavaScript中對閉包的理解


1、JS中變量的作用域

  • 在理解閉包之前,我們得弄清楚JS中變量的作用域原理,它分為全局作用域和局部作用域,它有一個特點就是局部可以獲取全局的聲明變量,而全局卻不能得到局部聲明的變量,我們先來看一個小例子:
		var num = 99;
		function foo(){
			var hit = 88;
			console.log(num);
		}
		foo();   //99
		console.log(hit);  //報錯,找不到hit變量

當然在局部聲明變量的時候一定要用var或者let,不然會在全局生成一個變量,容易照成全局污染,上面代碼如果hit沒有var聲明:

		var num = 99;
		function foo(){
			hit = 88;
			console.log(num);
		}
		foo();   //99
		console.log(hit);  //88

2、什么是閉包

那么現在問題來了,如果我們非要從外部來讀取局部變量中的聲明變量呢,尋常方式不行,我們可以變通一下,就是在函數內部再嵌套一個函數,然后返回這個嵌套函數:

		function foo(){
			var hit = 88;
			return function num(){
				console.log(hit)
			}
		}
		var num1 = foo();
		num1();  //88

這樣,控制台就會打印出hit變量的值了,其實在上面的代碼中,被返回的函數num()就產生了閉包,由於在js中,只有函數內部的子函數才能讀取局部變量,所以可以把閉包理解成定義在一個函數內部的函數,簡單的說,JavaScript允許使用內部函數:即函數定義和函數表達式位於另一個函數的函數體內。而且,這些內部函數可以訪問它們所在的外部函數中聲明的所有局部變量、參數和聲明的其他內部函數。當其中一個這樣的內部函數在包含它們的外部函數之外被調用時,就會形成閉包。

3、閉包的用途

  • 相信大家對閉包的概念已經有了簡單的認識,我們接着探討閉包的表達形式以及用途。
    (1)匿名自執行函數
		(function(){
		  var foo = function(){
		     console.log('執行完函數后銷毀')
		  };
		  foo();
		})();

上面代碼也是閉包的應用,運用於函數只會執行一次的場景,執行完便會被釋放。
(2)給對象設置私有變量

		var result = function(){
			var count = 1;
			  
			return function (){
				count++;
			    console.log(count)
			  }
		}()

		result(); //2
		result(); //3
		result(); //4
		result(); //5

上面代碼可以保存自己的私有變量,防止代碼之間的沖突。
(3)異步執行函數
下面先看一個小例子:

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

為什么會出現上述差異呢,原因在於setTimeout是異步加載,所以為先循環結束后輸出最后結果,如果我們就是想實現輸出0,1,2,3,4呢。那就要用到閉包了:

	for(var i=0;i<5;i++){

		(function(i){
			setTimeout(()=>{
				console.log(i); //0,1,2,3,4
			},0);
		})(i);
	}

上面就是異步調用閉包,它可以讓變量值始終保存在內存中,即使外部的執行環境已經結束了。

4、閉包的優缺點

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

(2)閉包會在父函數外部,改變父函數內部變量的值。所以,如果你把父函數當作對象(object)使用,把閉包當作它的公用方法(Public Method),把內部變量當作它的私有屬性(private value),這時一定要小心,不要隨便改變父函數內部變量的值。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM