來到es6厚脉,我們將有六種聲明變量央拖,有我們已經(jīng)學(xué)過的函數(shù)和var申尼,今天講的let 和const垮卓,還有后面講的import和class,話不多說师幕,我們先來講一下我們今天的let
let 的用法 和var差不多粟按,但是又不同于var诬滩,是為了完善之前的語法的不足而設(shè)計(jì)的,體現(xiàn)在它的塊級(jí)作用域灭将,因?yàn)樵谥暗恼Z法中只有全局作用域和函數(shù)作用域疼鸟,而在if 和 for 等語句中不存在作用域,也就是說if 和 for 里面的聲明輸入它們存在的函數(shù)作用域或者全局作用域庙曙。
塊級(jí)作用域
var a = [];
for (var i = 0; i < 10; i++){
a[i] = function(){
console.log(i)空镜;
}
}
a[6](); //10
在執(zhí)行循環(huán)的時(shí)候,系統(tǒng)只是將函數(shù)附給數(shù)組捌朴,但是并不會(huì)去解析函數(shù)里的內(nèi)容吴攒,直到最后一步執(zhí)行函數(shù)了,才會(huì)去解析里面的內(nèi)容男旗,這時(shí)候要訪問i舶斧,因?yàn)閕使用var聲明的,所以只存在于函數(shù)作用域或者全局作用域中察皇,這時(shí)候 i 會(huì)被放到全局作用域中,可是循環(huán)已經(jīng)結(jié)束了泽台,所以訪問到的i是全局重用域的10什荣;這并不是我們想要的效果,所以我們會(huì)使用一個(gè)叫立即執(zhí)行函數(shù)的方法來解決這個(gè)問題
var a = [];
for (var i = 0; i < 10; i++){
(function(k){
a[i] = function(){
console.log(i)怀酷;
}
}(k))
}
a[6](); //6
雖然這個(gè)問題得到了解決稻爬,但是也太過麻煩,這時(shí)候es6引入了塊級(jí)作用域蜕依,也就是說桅锄,用let 和 const聲明的變量除了可以在全局作用域和函數(shù)作用域中存在,還可以在塊級(jí)作用域中存在样眠。
var a = [];
for (let i = 0; i < 10; i++){
a[i] = function(){
console.log(i)友瘤;
}
}
a[6](); //6
也就是說,每次聲明的i都是一個(gè)新的變量檐束,只在當(dāng)前循環(huán)中有效存在于不同的塊級(jí)作用域中辫秧。
另外,在嚴(yán)格模式下被丧,if 盟戏,for 這些是不允許聲明函數(shù)的
不存在變量提升
還有一點(diǎn)就是let 不存在變量提升,什么是變量提升呢甥桂?這里我們先來介紹一下用預(yù)編譯柿究。每次在代碼執(zhí)行之前,瀏覽器會(huì)先對(duì)代碼進(jìn)行語法分析黄选,會(huì)通篇掃描一遍看看有沒有什么低級(jí)的錯(cuò)誤蝇摸,沒有的話進(jìn)行第二步,預(yù)編譯,預(yù)編譯一共分四步
1探入,創(chuàng)建一個(gè)AO對(duì)象
2狡孔,尋找形參和變量聲明,并將其作為屬性名放入AO對(duì)象中蜂嗽,屬性值都賦值為undefined
3苗膝,將實(shí)參和形參相統(tǒng)一
4,在函數(shù)里尋找函數(shù)聲明植旧,用其函數(shù)名作為屬性名放入AO中辱揭,屬性值為function;
這個(gè)AO就是我們通常說的上下文(Activeaction Object)病附,雖然里面是空的问窃,但是放著一些隱式屬性,如 this:window arguments:[]
介紹完了變量提升之后我們可以知道完沪,就算var聲明變量在聲明前面使用也是可以的域庇,但是這往往會(huì)帶來一些預(yù)想不到的錯(cuò)誤,所以let不允許函數(shù)在聲明之前使用覆积,一使用就報(bào)錯(cuò)听皿,而且let引入了暫時(shí)性死區(qū)的概念,來強(qiáng)化let聲明的變量不能提前使用宽档,什么是暫時(shí)性死區(qū)呢
暫時(shí)性死區(qū)
var a = 1;
if(ture){
console.log(a); //ReferrenceError
let a = 1;
}
為什么會(huì)報(bào)錯(cuò)呢尉姨?不是可以訪問外面的a嗎?
因?yàn)閘et所聲明的變量會(huì)鎖在它所在的作用域里,不允許訪問吗冤,就是說又厉,它也會(huì)先掃描一遍,把let聲明的變量保存起來椎瘟,但是不允許使用覆致,這時(shí)候你訪問a,由于此作用域中有a降传,就不用訪問外面的a了篷朵,但是你不能在它聲明之前訪問它。
不允許重復(fù)聲明
就是在同一個(gè)作用域中不允許重復(fù)聲明同一個(gè)變量婆排,而且也不能和形參重復(fù)声旺。
const
const有著let所有的特性,而它是用來聲明常量的段只,一是所聲明的變量不允許改變腮猖,二是聲明的時(shí)候必須賦值。但是對(duì)于復(fù)合類型的變量(如數(shù)組赞枕,對(duì)象)澈缺,const保存的只是地址坪创,里面的內(nèi)容還是可以改變的,如果想要整個(gè)對(duì)象都不允許改變姐赡,可以使用Object.freeze()方法
let constantice = function(obj){
Object.freeze(obj);
Object.keys(obj).forEach(function(key,value){
if(typeof obj[key] === 'Object'){
constantice (obj[key]);
}
})
}
全局對(duì)象的屬性
全局對(duì)象就是指最頂層的對(duì)象莱预,瀏覽器的是window,node的是global
在這里我們有必要了解一下项滑,在es5中依沮,全局對(duì)象的屬性全局和全局變量是等價(jià)的
一,暗示全局變量
一切未經(jīng)聲明的變量都會(huì)歸window所有枪狂,成為window的屬性
二危喉,一切用var聲明的全局變量都是window的屬性
那么有聲明和沒有聲明的全局變量都會(huì)成為window的屬性,有什么區(qū)別呢州疾?
沒有聲明的變量可以被刪除辜限,而聲明的不可以
1. a = 123;
2. console.log(window.a === a) // true
3. delete window.a;
4. console.log(window.a); // undefiend
5. var b = 123;
6. delete window.b;
7. console.log(window.b); // 123
三,而用let 严蓖,const 和 calss聲明的全局變量不歸window所有