摘要:大名鼎鼎的作用域和閉包,面試經(jīng)常會(huì)問到。聲明理解閉包,先理解函數(shù)的執(zhí)行過程。閉包的基本結(jié)構(gòu)因?yàn)殚]包不允許外界直接訪問,所以只能間接訪問函數(shù)內(nèi)部的數(shù)據(jù),獲得函數(shù)內(nèi)部數(shù)據(jù)的使用權(quán)。
大名鼎鼎的作用域和閉包,面試經(jīng)常會(huì)問到。閉包(closure)是Javascript語(yǔ)言的一個(gè)難點(diǎn),也是它的特色。
聲明理解閉包,先理解函數(shù)的執(zhí)行過程。
代碼在執(zhí)行的過程中會(huì)有一個(gè)預(yù)解析的過程,也就是在代碼的執(zhí)行過程中,會(huì)先將代碼讀取到內(nèi)存中,檢查其是否有錯(cuò)誤,然后將所有聲明在此進(jìn)行標(biāo)記,讓js解析器知道有這樣的一個(gè)名字,后面使用時(shí)便不會(huì)出現(xiàn)未定義的錯(cuò)誤,這個(gè)標(biāo)記的過程就是提升。
變量的聲明
var num;沒有與之對(duì)應(yīng)的數(shù)據(jù),僅僅是讓js解析器知道,你定義了一個(gè)num的變量。
函數(shù)的聲明
function foo(){};一個(gè)獨(dú)立的結(jié)構(gòu),沒有任何語(yǔ)句。首先是將函數(shù)名進(jìn)行提升,讓js解析器知道有一個(gè)foo函數(shù),接著是將函數(shù)名與函數(shù)體連接起來,注意這里并不執(zhí)行函數(shù)體。
代碼演示:
var num = 10; function foo(){ console.log(num); } foo();
預(yù)解析的過程(變量提升,函數(shù)提升):
var num; function foo(){ console.log(num) } num = 10; foo();
代碼執(zhí)行時(shí),首先會(huì)執(zhí)行 num = 10; 然后執(zhí)行foo(),進(jìn)行函數(shù)體,打印出num的值。此時(shí)的num訪問到的是全局中定義的num,所以num的值為10.
作用域以上代碼涉及到作用域的問題,所謂的域,表示的是范圍,所以作用域表示的是作用范圍,也就是一個(gè)名字在什么地方可以使用,在什么地方不可使用。
1、詞法作用域在js中,采用的是詞法作用域,詞法作用域是指在編寫代碼的過程中體現(xiàn)出來的作用范圍,一旦代碼寫好了,不用執(zhí)行,作用范圍就確定好了。
Javascript的作用域無非就是兩種:全局變量和局部變量。
2、詞法作用域的規(guī)則函數(shù)允許訪問函數(shù)外的數(shù)據(jù)
整個(gè)代碼結(jié)構(gòu)中只有函數(shù)可限定作用域
作用域規(guī)則首先使用提升規(guī)則分析
若當(dāng)前作用域中有名字了,就不考慮外面的名字
3、作用域鏈只有函數(shù)可以構(gòu)成作用域結(jié)構(gòu)。只要存在代碼,就至少有一個(gè)作用域,即全局作用域。凡是代碼有函數(shù),那么這個(gè)函數(shù)就構(gòu)成一個(gè)作用域,如果函數(shù)中還有函數(shù),那么在這個(gè)作用域中就又誕生一個(gè)作用域,那么將這樣的所有作用域列出來,就可以有一個(gè):函數(shù)內(nèi)指向函數(shù)外的鏈?zhǔn)浇Y(jié)構(gòu)。
作用域鏈變量訪問規(guī)則:看變量在當(dāng)前作用域中,是否有變量的定義與賦值,如果有,則直接使用;如果沒有,則到外面的作用域中查看,如果有,則停止查找,使用外面一層作用域中定義的變量或值,如果沒有,則繼續(xù)往外查找,直到最外層的全局,如果全局也沒有定義,則會(huì)報(bào)錯(cuò): xx is not defined。
閉包 什么是閉包閉包,是一個(gè)具有封閉功能與包裹功能的一個(gè)結(jié)構(gòu)或空間。在js中,函數(shù)可以構(gòu)成閉包。因?yàn)楹瘮?shù)在當(dāng)前的作用域中是一個(gè)封閉的結(jié)構(gòu),具有封閉性;同時(shí)根據(jù)作用域規(guī)則,只允許函數(shù)內(nèi)部訪問外部的數(shù)據(jù),而外部無法訪問函數(shù)內(nèi)部的數(shù)據(jù),即函數(shù)具有封閉的對(duì)外不公開的特性,就像把一個(gè)東西包裹起來一樣,因此函數(shù)可以構(gòu)成閉包。
有點(diǎn)難理解,簡(jiǎn)單來說,就是能夠讀取其他函數(shù)內(nèi)部變量的函數(shù),再簡(jiǎn)潔一點(diǎn)就是:定義在一個(gè)函數(shù)內(nèi)部的函數(shù)。
閉包的基本結(jié)構(gòu)因?yàn)殚]包不允許外界直接訪問,所以只能間接訪問函數(shù)內(nèi)部的數(shù)據(jù),獲得函數(shù)內(nèi)部數(shù)據(jù)的使用權(quán)。
function foo(){ var num = 123; function func(){ return num; } return func; } var f = foo(); var res1 = f(); var res2 = f(); // 此時(shí),foo只調(diào)用了一次,不會(huì)再內(nèi)存中重新創(chuàng)建一個(gè)函數(shù),而通過f,可以訪問并獲取num的值,那么調(diào)用f,即可獲得一樣的num值 改良: function foo(){ var num = 123; return function(){ return num; } } var f = foo(); var res1 = f(); var res2 = f(); 再改良: var f = (function foo(){ var num = 123; return function (){ return num; } })(); var res1 = f(); var res2 = f();
function func(){ var num1 = Math.random(); var num2 = Math.random(); return { num1: function(){ return num1; }, num2: function(){ return num2; } } } var p = func(); console.log(p.num1()); console.log(p.num1());// 這兩個(gè)訪問到的是同一個(gè)隨機(jī)數(shù)閉包的基本用法
如上面代碼演示的那樣,閉包可以通過返回函數(shù)來間接訪問到函數(shù)內(nèi)的數(shù)據(jù),這樣,閉包可以實(shí)現(xiàn)具有私有訪問空間的函數(shù),保護(hù)私有的數(shù)據(jù)。另一方面,可以幫助其他對(duì)象讀取到函數(shù)內(nèi)部的變量
閉包的性能問題函數(shù)定義的變量會(huì)在函數(shù)執(zhí)行結(jié)束后自動(dòng)回收,但是因?yàn)殚]包結(jié)構(gòu)引出的數(shù)據(jù)經(jīng)常會(huì)被外界所引用,這些數(shù)據(jù)將不會(huì)被回收,因此過多的閉包會(huì)消耗內(nèi)存資源,影響性能。所以要謹(jǐn)慎使用閉包,可以在使用閉包時(shí),如果不再使用某些變量了,一定要賦值一個(gè)null。
在ES6中,提出來對(duì)象代理概念,在代理層操作數(shù)據(jù)而不是直接操作原數(shù)據(jù)。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/100263.html
摘要:操作符或調(diào)用函數(shù)時(shí)傳入?yún)?shù)的操作都會(huì)導(dǎo)致關(guān)聯(lián)作用域的賦值操作。此外可以使用和來設(shè)置對(duì)象及其屬性的不可變性級(jí)別。忽視這一點(diǎn)會(huì)導(dǎo)致許多問題。使用調(diào)用函數(shù)時(shí)會(huì)把新對(duì)象的屬性關(guān)聯(lián)到其他對(duì)象。 前言 《你不知道的 javascript》是一個(gè)前端學(xué)習(xí)必讀的系列,讓不求甚解的JavaScript開發(fā)者迎難而上,深入語(yǔ)言內(nèi)部,弄清楚JavaScript每一個(gè)零部件的用途。本書介紹了該系列的兩個(gè)主題:...
摘要:用函數(shù)式編程對(duì)進(jìn)行斷舍離當(dāng)從業(yè)的老司機(jī)學(xué)會(huì)函數(shù)式編程時(shí),他扔掉了的特性,也不用面向?qū)ο罅?,最后發(fā)現(xiàn)了真愛啊作用域和閉包作用域和閉包在里非常重要。旨在幫助非函數(shù)式編程的同學(xué),能快速切入到函數(shù)式編程的理念。 1、用函數(shù)式編程對(duì)JavaScript進(jìn)行斷舍離 當(dāng)從業(yè)20的JavaScript老司機(jī)學(xué)會(huì)函數(shù)式編程時(shí),他扔掉了90%的特性,也不用面向?qū)ο罅?,最后發(fā)現(xiàn)了真愛?。。?! https:/...
摘要:用函數(shù)式編程對(duì)進(jìn)行斷舍離當(dāng)從業(yè)的老司機(jī)學(xué)會(huì)函數(shù)式編程時(shí),他扔掉了的特性,也不用面向?qū)ο罅?,最后發(fā)現(xiàn)了真愛啊作用域和閉包作用域和閉包在里非常重要。旨在幫助非函數(shù)式編程的同學(xué),能快速切入到函數(shù)式編程的理念。 1、用函數(shù)式編程對(duì)JavaScript進(jìn)行斷舍離 當(dāng)從業(yè)20的JavaScript老司機(jī)學(xué)會(huì)函數(shù)式編程時(shí),他扔掉了90%的特性,也不用面向?qū)ο罅?,最后發(fā)現(xiàn)了真愛?。。?! https:/...
摘要:用函數(shù)式編程對(duì)進(jìn)行斷舍離當(dāng)從業(yè)的老司機(jī)學(xué)會(huì)函數(shù)式編程時(shí),他扔掉了的特性,也不用面向?qū)ο罅?,最后發(fā)現(xiàn)了真愛啊作用域和閉包作用域和閉包在里非常重要。旨在幫助非函數(shù)式編程的同學(xué),能快速切入到函數(shù)式編程的理念。 1、用函數(shù)式編程對(duì)JavaScript進(jìn)行斷舍離 當(dāng)從業(yè)20的JavaScript老司機(jī)學(xué)會(huì)函數(shù)式編程時(shí),他扔掉了90%的特性,也不用面向?qū)ο罅?,最后發(fā)現(xiàn)了真愛啊?。?! https:/...
摘要:注意由于閉包會(huì)額外的附帶函數(shù)的作用域內(nèi)部匿名函數(shù)攜帶外部函數(shù)的作用域,因此,閉包會(huì)比其它函數(shù)多占用些內(nèi)存空間,過度的使用可能會(huì)導(dǎo)致內(nèi)存占用的增加。 作用域和作用域鏈?zhǔn)莏avascript中非常重要的特性,對(duì)于他們的理解直接關(guān)系到對(duì)于整個(gè)javascript體系的理解,而閉包又是對(duì)作用域的延伸,也是在實(shí)際開發(fā)中經(jīng)常使用的一個(gè)特性,實(shí)際上,不僅僅是javascript,在很多語(yǔ)言中都...
閱讀 3412·2023-04-26 01:40
閱讀 3107·2021-11-24 09:39
閱讀 1417·2021-10-27 14:19
閱讀 2662·2021-10-12 10:11
閱讀 1329·2021-09-26 09:47
閱讀 1868·2021-09-22 15:21
閱讀 2776·2021-09-06 15:00
閱讀 913·2021-08-10 09:44