亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

JavaScript作用域中閉包的用法

發布時間:2020-07-30 09:10:09 來源:億速云 閱讀:151 作者:小豬 欄目:開發技術

這篇文章主要講解了JavaScript作用域中閉包的用法,內容清晰明了,對此有興趣的小伙伴可以學習一下,相信大家閱讀完之后會有幫助。

JavaScript并不具有動態作用域,它只有詞法作用域。詞法作用域是在寫代碼或者說定義時確定的,而動態作用域是在運行時確定的。了解閉包前,首先我們得知道什么是詞法作用域(作用域是由書寫代碼時函數聲明的位置來決定的)。

一、何為閉包

示例1:

function foo(){
	var a = 2;
	function bar(){
		console.log(a);
	}
	return bar;
}
var baz = foo();
bzz(); //2

在foo()執行后,通常認為垃圾回收機制會將foo()的整個內部作用域都被銷毀;而閉包可以阻止這樣事情發生,讓其內部作用域依然存在。因為bar()處于foo()內部,它擁有涵蓋foo()作用域的閉包,使得該作用域能夠一直存活,以供bar()在之后任何時間進行引用。

bar()依然持有對該作用域的引用,而這個引用就叫作閉包。

簡言之:當函數可以記住并訪問所在的詞法作用域,即使函數是在當前詞法作用域之外執行,這時就產生了閉包。

示例2:

無論使用何種方式對函數類型的值進行傳遞,當函數在別處被調用時都可以觀察到閉包。

function foo(){
	var a = 2;
	function baz(){
		console.log(a);
	}
	bar(baz);
}

function bar(fn){
	fn();	// 這就是閉包
}

示例3:

將一個內部函數(timer)傳遞給setTimeout。timer具有涵蓋wait()作用域的閉包,保有對變量message的引用。

wait()執行1000毫秒后,它的作用域并不會消失,timer依然保有wait()作用域的閉包。

function wait(message){
	setTimeout( function timer(){
		console.log(message);
	},1000);
}
wait("Hello,ligang");

示例4:

下述activator()具有涵蓋setupBot()作用域的閉包!

function setupBot(name, selector){
	$(selector).click(function activator(){
		console.log("Activating: "+ name);
	});
}
setupBot("Closure Bot 1", "#bot_1");
setupBot("Closure Bot 2", "#bot_2");

二、循環和閉包

for(var i=1; i<=5; i++){
	setTimeout(function timer(){
		console.log(i);
	}, i*1000);
}
// 期望:每秒一次的頻率輸出1~5
// 結果:每秒一次的頻率輸出五次6

先解釋一下:“i*1000”,5個定時分別在1s、2s、3s、4s、5s后執行,并不是1s、3s、6s、10s、15s。也就是頻率為1s,不是每次間隔增加1s。如果去掉i寫成“1000”,會在for執行完1s后直接輸出五次6。

回調函數在循環結束后才被執行,因此輸出的是循環終止條件是i值。事實上,當定時器運行時即使每個迭代中執行的是setTimeout(..., 0),所有的回調函數依然是在循環結束后才被執行。

根據作用域的工作原理,盡管五個函數是在各個迭代中分別定義的,但是它們都被封閉在一個共享的全局作用域中,因此實際上只有一個i。

解決方案1:

for(var i=0; i<=5; i++){
	(function(j){
		setTimeout(function timer(){
			console.log(j);
		}, j*1000 );
	})(i);
}
// 結果:每秒一次的頻率輸出1~5

每個迭代都生成一個新的作用域,使得延遲函數的回調可以將新的作用封閉在每個迭代內部,每個迭代中都會含有一個具有正確值的變量供我們訪問。

解決方案2(ES6):

for(var i=0; i<=5; i++){
	let j = i;
	setTimeout(function timer(){
		console.log(j);
	}, j*1000 );
}
// 結果:每秒一次的頻率輸出1~5
for(let i=0; i<=5; i++){
	setTimeout(function timer(){
		console.log(i);
	}, i*1000 );
}
// 結果:每秒一次的頻率輸出五次6

三、模塊

模塊需要具備兩個必要條件:

(1)必須有外部的封閉函數,該函數必須至少被調用一次(每次調用都會創建一個新的模塊實例)。

(2)封閉函數必須返回至少一個內部函數,這樣內部函數才能在私有作用域中形成閉包,并且可以訪問或者修改私有的狀態。

典型的模塊化:

function CoolMoudle(){
	var something = "cool";
	var doSomething = function(){
		console.log(something);
	}
	return{
		doSomething: doSomething
	};
}
var foo = CoolMoudle();	//如果不執行外部函數CoolMoudle(),內部作用域和閉包都無法創建
foo.doSomething();	//cool

單例模式:

var foo = (function CoolModule(id){
	function change(){
		// 修改公共API
		publicAPI.identify = identify2;
	}
	function identify1(){
		console.log(id);
	}
	function identify2(){
		console.log(id.toUpperCase());
	}
	var publicAPI = {
		change: change,
		identify: identify1
	};
	return publicAPI;
})("foo module");
foo.identify();	//foo module
foo.change();
foo.identify(); //FOO MODULE

看完上述內容,是不是對JavaScript作用域中閉包的用法有進一步的了解,如果還想學習更多內容,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

高邮市| 汾西县| 大邑县| 运城市| 邢台县| 历史| 达孜县| 电白县| 高州市| 奉化市| 开化县| 祥云县| 高邮市| 和平县| 灵寿县| 广丰县| 策勒县| 太和县| 安陆市| 泽库县| 桃园县| 沈阳市| 湘乡市| 江油市| 贵德县| 水富县| 巧家县| 拉孜县| 册亨县| 勐海县| 江安县| 绿春县| 卢氏县| 新余市| 杭锦后旗| 金山区| 方正县| 宾川县| 赣州市| 澎湖县| 光泽县|