最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解JavaScript作用域 閉包

 更新時間:2020年07月29日 15:28:49   作者:看云  
這篇文章主要介紹了JavaScript作用域 閉包的相關(guān)資料,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下

JavaScript閉包,是JS開發(fā)工程師必須深入了解的知識。3月份自己曾撰寫博客《JavaScript閉包》,博客中只是簡單闡述了閉包的工作過程和列舉了幾個示例,并沒有去刨根問底,將其弄明白!

現(xiàn)在隨著對JavaScript更深入的了解,也剛讀完《你不知道的JavaScript(上卷)》這本書,所以乘機(jī)整理下,從底層和原理上去刨一下。

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

一、何為閉包

示例1:

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

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

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

簡言之:當(dāng)函數(shù)可以記住并訪問所在的詞法作用域,即使函數(shù)是在當(dāng)前詞法作用域之外執(zhí)行,這時就產(chǎn)生了閉包。

示例2:

無論使用何種方式對函數(shù)類型的值進(jìn)行傳遞,當(dāng)函數(shù)在別處被調(diào)用時都可以觀察到閉包。

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

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

示例3:

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

wait()執(zhí)行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");

二、循環(huán)和閉包

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

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

回調(diào)函數(shù)在循環(huán)結(jié)束后才被執(zhí)行,因此輸出的是循環(huán)終止條件是i值。事實上,當(dāng)定時器運行時即使每個迭代中執(zhí)行的是setTimeout(..., 0),所有的回調(diào)函數(shù)依然是在循環(huán)結(jié)束后才被執(zhí)行。

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

解決方案1:

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

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

解決方案2(ES6):

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

三、模塊

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

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

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

典型的模塊化:

function CoolMoudle(){
	var something = "cool";
	var doSomething = function(){
		console.log(something);
	}
	return{
		doSomething: doSomething
	};
}
var foo = CoolMoudle();	//如果不執(zhí)行外部函數(shù)CoolMoudle(),內(nèi)部作用域和閉包都無法創(chuàng)建
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作用域 閉包的詳細(xì)內(nèi)容,更多關(guān)于JavaScript作用域 閉包的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • js數(shù)組方法reduce經(jīng)典用法代碼分享

    js數(shù)組方法reduce經(jīng)典用法代碼分享

    本文給大家整理了很多關(guān)于js數(shù)組方法reduce的經(jīng)典代碼片段,能夠讓大家更好的理解reduce的實例用法,一起學(xué)習(xí)下吧。
    2018-01-01
  • JS判斷兩個時間大小的示例代碼

    JS判斷兩個時間大小的示例代碼

    本篇文章只要是對JS判斷兩個時間大小的示例代碼進(jìn)行了介紹,需要的朋友可以過來參考下,希望對大家有所幫助
    2014-01-01
  • 詳解JavaScript中的作用域鏈與閉包

    詳解JavaScript中的作用域鏈與閉包

    這篇文章主要為大家詳細(xì)介紹一下JavaScript中的作用域鏈與閉包的使用,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)JavaScript有一定的幫助,需要的可以參考一下
    2022-11-11
  • 原生JS實現(xiàn)可拖拽登錄框

    原生JS實現(xiàn)可拖拽登錄框

    這篇文章主要為大家詳細(xì)介紹了原生JS實現(xiàn)可拖拽登錄框,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • 在weex中愉快的使用scss的方法步驟

    在weex中愉快的使用scss的方法步驟

    這篇文章主要介紹了在weex中愉快的使用scss的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-01-01
  • 一個仿微博登陸郵箱提示框js開發(fā)案例

    一個仿微博登陸郵箱提示框js開發(fā)案例

    這篇文章主要為大家詳細(xì)介紹了一個仿郵箱登錄提示框js開發(fā)案例,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-07-07
  • js鼠標(biāo)按鍵事件和鍵盤按鍵事件用法實例匯總

    js鼠標(biāo)按鍵事件和鍵盤按鍵事件用法實例匯總

    這篇文章主要介紹了js鼠標(biāo)按鍵事件和鍵盤按鍵事件用法,結(jié)合實例形式總結(jié)分析了JavaScript針對鼠標(biāo)與鍵盤事件的常用操作技巧,需要的朋友可以參考下
    2016-10-10
  • Bootstrap模態(tài)對話框中顯示動態(tài)內(nèi)容的方法

    Bootstrap模態(tài)對話框中顯示動態(tài)內(nèi)容的方法

    今天小編就為大家分享一篇Bootstrap模態(tài)對話框中顯示動態(tài)內(nèi)容的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-08-08
  • javascript中的previousSibling和nextSibling的正確用法

    javascript中的previousSibling和nextSibling的正確用法

    這篇文章主要介紹了javascript中的previousSibling和nextSibling的正確用法的相關(guān)資料,需要的朋友可以參考下
    2015-09-09
  • JS實現(xiàn)點擊事件統(tǒng)計的簡單實例

    JS實現(xiàn)點擊事件統(tǒng)計的簡單實例

    下面小編就為大家?guī)硪黄狫S實現(xiàn)點擊事件統(tǒng)計的簡單實例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-07-07

最新評論

钦州市| 平江县| 丽水市| 黄石市| 金寨县| 峡江县| 岗巴县| 湟中县| 新乡县| 独山县| 凯里市| 白河县| 临洮县| 德江县| 搜索| 图木舒克市| 长宁区| 上高县| 张掖市| 资溪县| 杭锦后旗| 醴陵市| 德令哈市| 依兰县| 福州市| 乌什县| 昌平区| 邓州市| 广平县| 横山县| 双辽市| 大田县| 荆门市| 县级市| 钦州市| 敦煌市| 平陆县| 轮台县| 曲沃县| 棋牌| 宜宾市|