咱們首先來回顧一下,咱們?cè)诳蛻舳藶g覽器學(xué)的關(guān)于作用域的東西仔燕,回憶一下造垛,作用域有幾種當(dāng)時(shí)學(xué)的?恩晰搀,對(duì)五辽,有二種,一種叫全局作用域厕隧,一種叫函數(shù)作用域奔脐,也叫局部作用域:
<script>
var a = 123;//這個(gè)變量a是全局級(jí)別的作用域
var fn = function(){//函數(shù)fn屬于全局作用域級(jí)下面的函數(shù)
//這里是屬于局部作用域,下面的a,b變量是屬于當(dāng)前這個(gè)局部作用域的變量
var a = 234;
var b = 344;
}
</script>
關(guān)于全局作用域的變量或函數(shù)使用原則是:'''代碼從上往下執(zhí)行吁讨,只要在上面的代碼定義過某全局變量或函數(shù)髓迎,那么在任何地方都可以使用這個(gè)全局的變量或函數(shù)'''。
關(guān)于局部作用域的變量或函數(shù)使用原則是:'''當(dāng)前這個(gè)函數(shù)被調(diào)用或叫被使用的時(shí)候建丧,在當(dāng)前局部作用域里定義的變量可以在當(dāng)前作用域被使用排龄,超出這個(gè)作用域范圍之后是訪問不到這個(gè)變量或函數(shù)的'''。
<script>
var a = 100;
var fn = function(){
console.log("fn函數(shù)被調(diào)用");
}
var fn1 = function(){
var b = 123;
console.log(b);//b是屬于當(dāng)前這個(gè)函數(shù)級(jí)作用域
console.log(a);//在函數(shù)級(jí)作用域里也可以使用全局變量a
fn();//在函數(shù)級(jí)作用域里也可以使用全局函數(shù)fn
}
fn1();
console.log(b);//會(huì)報(bào)錯(cuò)翎朱,因?yàn)槲覀冎挥性趂n1函數(shù)級(jí)作用域里定義過變量b
</script>
另外橄维,不是說在局部作用域里定義的變量或函數(shù)就一定是屬于當(dāng)前這個(gè)作用域,我們還可以通過代理global的全局最大對(duì)象window來在局部作用域里面定義全局變量或函數(shù):
<script>
var fn = function(){
window.a = 123;
window.fn1 = function(){
console.log("fn1函數(shù)被調(diào)用");
}
}
fn();
console.log(a);//結(jié)果是123
fn1();
</script>
當(dāng)然拴曲,作用域嵌套作用域的情況又會(huì)產(chǎn)生一個(gè)好玩的東西叫閉包:
<script>
function fn(a){
var b = 100;
var fn1 = function(){
b++;
console.log(a + b);
}
return fn1;
}
var myFn = fn(100);
myFn();
myFn();
</script>
到此為止咱們就復(fù)習(xí)完了咱們的客戶端瀏覽器端學(xué)習(xí)的作用域的知識(shí)争舞,現(xiàn)在咱們?cè)倮^續(xù)學(xué)一些其他類型的作用域的知識(shí):
咱們來看一下咱們的node.js,在咱們的node.js里面學(xué)過一個(gè)東西叫模塊澈灼,模塊的思想其實(shí)是來源于生活的竞川,咱們?cè)谄綍r(shí)的情況下有時(shí)候處理一個(gè)東西太復(fù)雜了店溢,不太好研究,咱們會(huì)習(xí)慣性的把這個(gè)事物這個(gè)東西分成一塊一塊的來研究委乌,最常見的就是比如人床牧,咱們就會(huì)把一個(gè)人分為免疫系統(tǒng)、血液系統(tǒng)等各個(gè)系統(tǒng)遭贸,或者像咱們的汽車戈咳,咱們會(huì)把它分成發(fā)動(dòng)機(jī)啊、車胎啊之類的壕吹。在咱們的node.js這個(gè)平臺(tái)里面著蛙,咱們會(huì)把一個(gè)js文件(node文件、json文件)當(dāng)成一個(gè)模塊算利。這時(shí)候就會(huì)出現(xiàn)一種新的作用域叫模塊級(jí)別的作用域册踩。
然后,除了模塊級(jí)作用域之外效拭,在ES3和ES5里面暂吉,咱們想定義一個(gè)變量一般會(huì)采用的是:
var a = 100;
但是這樣定義一個(gè)變量會(huì)有問題的,什么情況下會(huì)出現(xiàn)問題呢缎患?咱們可以看一下面的這段代碼:
"use strict";
if(false){
var a = 1;
}
console.log(a);
雖然if里的條件表達(dá)式的值是false,但是咱們打印a卻不會(huì)報(bào)錯(cuò)慕的,結(jié)果是undefined,這個(gè)原因在這里也不細(xì)究了(大家可以復(fù)習(xí)一下預(yù)解析相關(guān)的知識(shí)點(diǎn)的內(nèi)容)。
所以挤渔,為了避免這個(gè)問題肮街,在ES6中就有了一個(gè)新的用來定義一個(gè)變量的關(guān)鍵字叫l(wèi)et,比如下面的這段代碼:
"use strict";
if(false){
let a = 1;
}
console.log(a);
這個(gè)時(shí)候就會(huì)報(bào)錯(cuò)判导,因?yàn)檫@時(shí)候不會(huì)有一個(gè)變量叫a嫉父,因?yàn)椴淮嬖谧兞孔饔糜蛱嵘恕2坏绱搜廴校蹅冊(cè)倏匆欢未a如下:
"use strict";
if(true){
let a = 1;
}
console.log(a);
這段代碼 也是報(bào)錯(cuò)绕辖,這個(gè)原因就是因?yàn)槿绻昧薼et關(guān)鍵字以后呢,就會(huì)出現(xiàn)一種新的作用域叫塊級(jí)作用域擂红,塊級(jí)作用域只會(huì)存在于當(dāng)前這個(gè)花括號(hào)內(nèi)部仪际。
塊級(jí)作用域和let個(gè)人覺得最有用的應(yīng)該是在好多情況下本來需要閉包,現(xiàn)在不需要了昵骤,可以簡(jiǎn)化代碼:
"use strict";
for(let i=0;i<5;i++){
setTimeout(function(){
console.log(i);
},100);
}