作用域是什么掉瞳?
抱著這個疑問,咱們不妨先看看下面的一段代碼
var name = 'tony';
function hello(age){
console.log(name);
console.log(age);
console.log(fullName);
}
hello();
//tony
//undefined
//fullName is not defined
實(shí)際運(yùn)行結(jié)果
如果不了解作用域的看到代碼可能會和我一樣疑惑行冰,為什么fullname“no defined”而age是"undefined",有什么區(qū)別某宪,以及為啥是"no defined"?
有了這樣的疑問我們再來看看我們所看到的一些解釋:
作用域解釋1
作用域解釋2
從這個兩個解釋里面我們可以提取出來兩個要點(diǎn)锐朴,規(guī)則 集合
規(guī)則其實(shí)不難理解兴喂,就如同我們?nèi)嗽谏鐣幸粯樱艿礁鞣N規(guī)則限制,而在js中處處存在的變量衣迷,也同樣受到一套規(guī)則所限畏鼓,同樣有“生老病死”(變量生命周期),同樣有自己的“人生軌跡”(作用域鏈)壶谒。
在js中變量所受的作用域規(guī)則主要有了 全局作用域云矫,局部作用域,塊狀作用域汗菜,動態(tài)作用域让禀,
這些作用域在上面的代碼就有體現(xiàn),我們可以先從我們最容易看懂的name變量入手陨界,變量name是在整個代碼中的最外層的,即在函數(shù)外,代碼塊{}
外(es6新增)的,這就是全局作用域.
我們說作用域是變量在整個js代碼中運(yùn)行的規(guī)則巡揍,這時候name在全局作用域的規(guī)則下就是:網(wǎng)頁中所有腳本和函數(shù)均可使用,
全局作用域聲明的變量可以在函數(shù)內(nèi)部修改
我們再把這段代碼修改一下菌瘪,就可以通過對比加深對全局作用域的理解腮敌,同時知道什么是函數(shù)作用域了
全局作用域的變量和函數(shù)作用域的變量
函數(shù)內(nèi)部定義的變量age,在函數(shù)內(nèi)部定義的俏扩,就是局部作用域糜工,很明顯,它的規(guī)則就是只能在函數(shù)內(nèi)部訪問动猬,你看在其它函數(shù)內(nèi)修改也改變不了內(nèi)部27的事實(shí)啤斗。在修改age的這個函數(shù)內(nèi)表箭,涉及到了js的變量提升編譯詞法等(看這里)赁咙,你在函數(shù)外打印age這個變量是可以得到20的,這更加說明了作用域的存在免钻,超出了作用域彼水,即便名字相同,也是不同的變量极舔。這也是由于不同作用域可訪問的變量不同導(dǎo)致的凤覆,可以再看一眼作用域的解釋:
作用域?yàn)榭稍L問對象,變量拆魏,函數(shù)的集合
在函數(shù)內(nèi)部盯桦,存在的可訪問變量有name,age渤刃,在函數(shù)內(nèi)部查找不到name這個變量時拥峦,會找到上一層全局作用域中,而查找age時卖子,在局部作用域中就找到了略号,所以不會再在全局作用域中進(jìn)行查找。
作為局部作用域定義的變量可以很好的受到保護(hù),不在外部就被隨意更改玄柠,但是比如年齡這個東西突梦,總不能每年詢問的時候總是那個歲數(shù)吧
局部作用域的變量每次訪問都被重置
所以我們需要每次訪問的時候讓函數(shù)內(nèi)部自己+1。類似這樣
plus函數(shù)就包含了它上一層的作用域中的變量age羽利,但由于plus函數(shù)也是局部作用域中宫患,所以每次訪問也是同樣的值,如果能夠?qū)lus這個操作这弧,做成類似全局作用域撮奏,那么每次執(zhí)行就不會是重復(fù)的值了
閉包實(shí)際就是將局部作用域的集合調(diào)到全局作用域中,使局部作用域中的變量不被銷毀
閉包是解決這個問題的一個方法当宴,用立即執(zhí)行函數(shù)返回的一個函數(shù)畜吊,成為了全局作用域下的一個變量集合,集合也可以是函數(shù)噢户矢,所以玲献,這個函數(shù)內(nèi)部使用的變量,雖然是在局部作用域下的梯浪,但是卻不會被銷毀捌年。
這兩個作用域基本上就是es5中經(jīng)常使用的了,在es6中挂洛,新增了塊狀作用域礼预, 起初我以為這個作用域的規(guī)則是針對所有變量的,但經(jīng)過試驗(yàn)虏劲,這個規(guī)則主要配合let
聲明的變量使用托酸,用來解決以前es5中一些場景下變量使用的作用域模糊不清的問題,比如常見的這種
for(var i = 0;i < 3;i++){}
console.log(i) //3
如果換成let來聲明i變量柒巫,就會報錯ReferenceError
励堡,另外還有一種變量聲明const,同樣受此規(guī)則限制堡掏,所以应结,用let,const聲明的變量僅在當(dāng)前{}
中可以訪問泉唁。
大概就說這些作用域了鹅龄,總結(jié):作用域是變量在一段代碼中的訪問規(guī)則,是可訪問變量的集合亭畜。