摘要:局部變量在函數(shù)中聲明的變量,函數(shù)的參數(shù)作用域是局部性的,在函數(shù)體外,或者說(shuō)的當(dāng)前作用域的上層是無(wú)法直接讀取的。執(zhí)行結(jié)果這樣我們就在外層取得了函數(shù)內(nèi)部局部變量的也就是閉包實(shí)現(xiàn)從外部讀取局部變量的能力。
淺談作用域
??當(dāng)我們新建一個(gè)可以儲(chǔ)存變量的值,怎么才能讀取到這個(gè)變量呢?能訪問(wèn)到這個(gè)變量,就說(shuō)明符合作用域規(guī)則,作用域規(guī)則就可以說(shuō)是js引擎讀取變量的規(guī)則。
??在js中變量分為兩種,全局變量和局部變量,全局變量(擁有全局作用域)可以在整個(gè)js應(yīng)用中被所有代碼訪問(wèn)到,從程序開始分配內(nèi)存直至結(jié)束才會(huì)被釋放(出于對(duì)代碼的性能、可讀性、以及潛在沖突考慮應(yīng)該減少使用)。
??局部變量在函數(shù)中聲明的變量,函數(shù)的參數(shù)(作用域是局部性的),在函數(shù)體外,或者說(shuō)的當(dāng)前作用域的上層是無(wú)法直接讀取的。
??下面再說(shuō)下作用域嵌套,產(chǎn)生作用域鏈的事,在我們實(shí)際編寫代碼的時(shí)候,比如:
var a = "a"; function demo(b) { let c = "c"; function print(c) { console.log(a + " " + b + " " + c); } print(c); } demo("b");
執(zhí)行結(jié)果:
??在print方法執(zhí)行的時(shí)候,會(huì)從當(dāng)前的執(zhí)行作用域開始查找變量,如果找不到,就繼續(xù)向上一級(jí)繼續(xù)查找,如果找到則會(huì)停止,如果沒有就會(huì)繼續(xù)直至當(dāng)最后到達(dá)全局作用域時(shí),此時(shí)無(wú)論找到還是沒找到,都會(huì)結(jié)束查找。
st=>start: 當(dāng)前作用域 io1=>start: 上層作用域 io2=>start: ... cond=>end: 全局作用域 st->io1->io2->cond
??(簡(jiǎn)單寫了個(gè)流程圖方便腦補(bǔ))
??接下來(lái)還是這段代碼讓我們來(lái)做一個(gè)小小的修改。
var a = "a"; function demo(b) { let c = "c", a = "d"; function print(c) { console.log(a + " " + b + " " + c); } print(c); } demo("b");
執(zhí)行結(jié)果:
??結(jié)果是輸出了上一層的變量a,這也就是作用域查找的機(jī)制,作用域始終從運(yùn)行時(shí)所處的最內(nèi)部作用域開始,逐漸向外層查找,當(dāng)遇到第一個(gè)符合條件的結(jié)果就會(huì)返回,停止查找。
變量提升??先簡(jiǎn)單上一段代碼
a = "a"; var a; console.log(a);
執(zhí)行結(jié)果:
??為什么會(huì)有這種結(jié)果呢?聲明在后,反而打印出前面聲明得值,其實(shí)js在編譯的時(shí)候會(huì)先進(jìn)行聲明操作,之后再進(jìn)行賦值操作,也就是只要是在作用域中的聲明一出現(xiàn),就將在代碼本身被執(zhí)行前優(yōu)先進(jìn)行處理。也可以將這個(gè)過(guò)程理解為所有的聲明(變量和函數(shù))都會(huì)被“提升”到作用域的最頂端。(雖然函數(shù)聲明和變量聲明都會(huì)被提升,但是函數(shù)優(yōu)先級(jí)要高于變量)
(在ES6引入了let和const可以用來(lái)聲明創(chuàng)建塊作用域。for循環(huán)頭部定義強(qiáng)烈建議用let,感興趣的人可以去看看js函數(shù)作用域和塊作用域)
閉包??提到閉包很多人腦袋里都會(huì)感覺模模糊糊的,閉包在概念上定義是能夠讀取其他函數(shù)內(nèi)部變量的函數(shù),在中,只有函數(shù)內(nèi)部的子函數(shù)才能讀取這個(gè)函數(shù)局部變量,這時(shí)候前面說(shuō)的作用域起到作用了,所以我們現(xiàn)在可以這樣理解,定義在一個(gè)函數(shù)內(nèi)部的函數(shù),這個(gè)函數(shù)可以訪問(wèn)其他函數(shù)的變量,就可以稱為“閉包”。
??下面來(lái)聊聊閉包的用處,主要就是。1.能夠讀取到函數(shù)內(nèi)部的變量,2.可以讓變量始終保存在內(nèi)存中(這點(diǎn)要注意后面解釋),下面上代碼。
function demo() { let a = "a"; function print() { console.log(a); } return print; } var clo = demo(); clo();
執(zhí)行結(jié)果:
??這樣我們就在外層取得了demo函數(shù)內(nèi)部局部變量的a,也就是閉包實(shí)現(xiàn)從外部讀取局部變量的能力。
??下面說(shuō)一說(shuō)讓變量始終保存在內(nèi)存中這點(diǎn).
function demo() { let a = 1; addA = () => a+=1; function print() { console.log(a); } return print; } var clo = demo(); clo(); addA(); clo();
執(zhí)行結(jié)果:
??閉包可以阻止,demo內(nèi)部作用域都被垃圾清理機(jī)制回收銷毀,可以看到局部變量a第二次執(zhí)行比第一次+1,這就說(shuō)明第一次運(yùn)行結(jié)束后啊,沒有被回收,因?yàn)閜rint()仍在使用這個(gè)作用域所以demo不會(huì)被回收。
(閉包會(huì)使得對(duì)應(yīng)的變量一直保存在內(nèi)存中,不會(huì)被清理回收,對(duì)內(nèi)存消耗大,別濫用)
??1.原生的setTimeout傳遞的函數(shù)不能帶參數(shù)
//會(huì)報(bào)錯(cuò) function func(param){ console.log(param); } var test = func(1); setTimeout(test, 1000); //通過(guò)閉包實(shí)現(xiàn)傳參效果 function func(param){ return function(){ console.log(param); } } var test = func(1); setTimeout(test, 1000);
??2.封裝變量
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/102721.html
摘要:塊狀作用域提起中的關(guān)鍵字,第一個(gè)想法就是塊狀作用域。而如果通過(guò)這些關(guān)鍵詞聲明的,那么也就會(huì)聲明到所在的作用域中。終于回到可以將變量綁定到所在的任意作用域中,通常是內(nèi)部。避免不必要的出現(xiàn)。 讀,想到哪里寫到哪里。。。 塊狀作用域 提起ES6中的let關(guān)鍵字,第一個(gè)想法就是塊狀作用域。 說(shuō)到作用域,以前提及的都是全局作用域和函數(shù)作用域。當(dāng)進(jìn)行作用域查找的時(shí)候,永遠(yuǎn)是一層一層往上查找,直到找...
摘要:有何區(qū)別在中,存在關(guān)鍵字,它聲明的變量同樣存在塊級(jí)作用域。而且函數(shù)本身的作用域,只存在其所在的塊級(jí)作用域之內(nèi),例如重復(fù)聲明一次函數(shù)上面這段代碼在中的輸出結(jié)果為因?yàn)楸粭l件語(yǔ)句中的上升覆蓋了。如果對(duì)的使用,或的其他新特性感興趣,請(qǐng)自行閱讀文檔。 引子 首先大家看一下下面的代碼,猜猜會(huì)輸出什么結(jié)果? var foo = 1; function bar() { if (!foo) { ...
摘要:盡可能的使用局部變量,少用全局變量。正確的實(shí)現(xiàn)就是在函數(shù)體內(nèi)部使用將聲明成局部變量。在新特性中,引入了塊級(jí)作用域這個(gè)概念,因此還可以使用,來(lái)聲明局部變量。它們共享外部變量,并且閉包還可以更新的值。 變量作用域 作用域,對(duì)于JavaScript語(yǔ)言來(lái)說(shuō)無(wú)處不在,變量作用域,函數(shù)作用域(運(yùn)行時(shí)上下文和定義時(shí)上下文),作用域污染等等都跟作用域息息相關(guān),掌握J(rèn)avaScript作用于規(guī)則,可以...
摘要:閉包是什么這是一個(gè)在面試的過(guò)程中出現(xiàn)的概率為以上的問(wèn)題,也是我們張口就來(lái)的問(wèn)題。文章推薦我們面試中在被問(wèn)到閉包這個(gè)問(wèn)題是要注意的幾點(diǎn)閉包的延伸,讓面試變得 閉包是什么?這是一個(gè)在面試的過(guò)程中出現(xiàn)的概率為60%以上的問(wèn)題,也是我們張口就來(lái)的問(wèn)題。但是我們往往發(fā)現(xiàn),在面試的過(guò)程中我們的回答并不那么讓面試官滿意,我們雖然能張口說(shuō)出一些但是卻不能系統(tǒng)的對(duì)這個(gè)問(wèn)題進(jìn)行回答。面試官希望加入自己團(tuán)隊(duì)...
摘要:垃圾回收內(nèi)存管理實(shí)踐先通過(guò)一個(gè)來(lái)看看在中進(jìn)行垃圾回收的過(guò)程是怎樣的內(nèi)存泄漏識(shí)別在環(huán)境里提供了方法用來(lái)查看當(dāng)前進(jìn)程內(nèi)存使用情況,單位為字節(jié)中保存的進(jìn)程占用的內(nèi)存部分,包括代碼本身?xiàng)6选? showImg(https://segmentfault.com/img/remote/1460000019894672?w=640&h=426);作者 | 五月君Node.js 技術(shù)棧 | https:...
閱讀 1669·2023-04-26 00:25
閱讀 980·2021-09-27 13:36
閱讀 991·2019-08-30 14:14
閱讀 2242·2019-08-29 17:10
閱讀 1076·2019-08-29 15:09
閱讀 2008·2019-08-28 18:21
閱讀 1035·2019-08-26 13:27
閱讀 1042·2019-08-26 10:58