理解js閉包9大使用場景


1.返回值(最常用)

	//1.返回值 最常用的
		function fn(){
			var name="hello";
			return function(){
				return name;
			}
		}
		var fnc = fn();
		console.log(fnc())//hello

這個很好理解就是以閉包的形式將 name 返回。

2.函數賦值

        var fn2;
		function fn(){
			var name="hello";
			//將函數賦值給fn2
			fn2 = function(){
				return name;
			}
		}
		fn()//要先執行進行賦值,
		console.log(fn2())//執行輸出fn2

在閉包里面給fn2函數設置值,閉包的形式把name屬性記憶下來,執行會輸出 hello。

3.函數參數

		function fn(){
			var name="hello";
			return function callback(){
				return name;
			}
		}
		var fn1 = fn()//執行函數將返回值(callback函數)賦值給fn1,
		
		function fn2(f){
			//將函數作為參數傳入
			console.log(f());//執行函數,並輸出
		}
		fn2(fn1)//執行輸出fn2

用閉包返回一個函數,把此函數作為另一個函數的參數,在另一個函數里面執行這個函數,最終輸出 hello

4.IIFE(自執行函數)

	(function(){
			var name="hello";
			var fn1= function(){
				return name;
			}
			//直接在自執行函數里面調用fn2,將fn1作為參數傳入
			fn2(fn1);
		})()
		function fn2(f){
			//將函數作為參數傳入
			console.log(f());//執行函數,並輸出
		}

直接在自執行函數里面將封裝的函數fn1傳給fn2,作為參數調用同樣可以獲得結果 hello

5.循環賦值

	//每秒執行1次,分別輸出1-10
	for(var i=1;i<=10;i++){
		(function(j){
			//j來接收
			setTimeout(function(){
				console.log(j);
			},j*1000);
		})(i)//i作為實參傳入
	}

如果不采用閉包的話,會有不一樣的情況,可以看我自己 閉包 的文章。

6.getter和setter

function fn(){
		var name='hello'
		setName=function(n){
			name = n;
		}
		getName=function(){
			return name;
		}
		
		//將setName,getName作為對象的屬性返回
		return {
			setName:setName,
			getName:getName
		}
	}
	var fn1 = fn();//返回對象,屬性setName和getName是兩個函數
	console.log(fn1.getName());//getter
		fn1.setName('world');//setter修改閉包里面的name
	console.log(fn1.getName());//getter

第一次輸出 hello 用setter以后再輸出 world ,這樣做可以封裝成公共方法,防止不想暴露的屬性和函數暴露在外部。

7.迭代器(執行一次函數往下取一個值)

		var arr =['aa','bb','cc'];
		function incre(arr){
			var i=0;
			return function(){
				//這個函數每次被執行都返回數組arr中 i下標對應的元素
				 return arr[i++] || '數組值已經遍歷完';
			}
		}
		var next = incre(arr);
		console.log(next());//aa
		console.log(next());//bb
		console.log(next());//cc
		console.log(next());//數組值已經遍歷完

8.首次區分(相同的參數,函數不會重復執行)

 var fn = (function(){
				var arr=[];//用來緩存的數組
					return function(val){
						if(arr.indexOf(val)==-1){//緩存中沒有則表示需要執行
							arr.push(val);//將參數push到緩存數組中
							console.log('函數被執行了',arr);
							//這里寫想要執行的函數
						}else{
							console.log('此次函數不需要執行');
						}
						console.log('函數調用完打印一下,方便查看已緩存的數組:',arr);
					}
				})();
		
		fn(10);
		fn(10);
		fn(1000);
		fn(200);
		fn(1000);

執行結果如下:

可以明顯的看到首次執行的會被存起來,再次執行直接取。

9.緩存

//比如求和操作,如果沒有緩存,每次調用都要重復計算,采用緩存已經執行過的去查找,查找到了就直接返回,不需要重新計算
	 
	 var fn=(function(){
	 	var cache={};//緩存對象
	 	var calc=function(arr){//計算函數
	 		var sum=0;
	 		//求和
	 		for(var i=0;i<arr.length;i++){
		 		sum+=arr[i];
		 	}
		 	return sum;
	 	}
	 	
	 	return function(){
	 		var args = Array.prototype.slice.call(arguments,0);//arguments轉換成數組
	 		var key=args.join(",");//將args用逗號連接成字符串
		 	var result , tSum = cache[key];
		 	if(tSum){//如果緩存有	
		 		console.log('從緩存中取:',cache)//打印方便查看
		 		result = tSum;
		 	}else{
		 		//重新計算,並存入緩存同時賦值給result
			 	result = cache[key]=calc(args);
			 	console.log('存入緩存:',cache)//打印方便查看
		 	}
		 	return result;
	 	}
	 })();
	fn(1,2,3,4,5);
	fn(1,2,3,4,5);
	fn(1,2,3,4,5,6);
	fn(1,2,3,4,5,8);
	fn(1,2,3,4,5,6);

輸出結果:

 

轉載於:https://blog.csdn.net/dkm123456/article/details/111644638


免責聲明!

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



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