哈嘍大家好,又見面啦蹭睡,我依舊是那個可愛的蛙人衍菱。
今天又周五了啊,劃水人的一天肩豁,開心脊串。
話不多說哈,直接摟代碼
var 變量提升機制
我們在全局作用域中或還是在局部作用域中清钥,使用var
關鍵字聲明的變量琼锋,都會被提升到該作用域的最頂部,這就是我們常說的變量提升循捺。
function person(status) {
if (status) {
var value = "蛙人"
} else {
console.log(value) // undefined
}
console.log(value) // undefined
}
person(false)
上面example中斩例,if
代碼塊中的var聲明的變量就被提升到了函數(shù)的頂端雄人,有的小伙伴就會疑惑了从橘,if
代碼塊里的都沒執(zhí)行,怎么會提升到頂端了呢础钠?恰力,這是因為javaScript引擎,在代碼預編譯時旗吁,javaScript引擎會自動將所有代碼里面的var
關鍵字聲明的語句都會提升到當前作用域的頂端, 因此上面的代碼就會被解析為下面踩萎。
function person(status) {
var value;
if (status) {
value = "蛙人"
} else {
console.log(value) // undefined
}
console.log(value) // undefined
}
person(false)
由于javaScript存在變量提升,這讓很多開發(fā)者初學起來這門語言很钓,還得花不少時間研究變量提升香府,也有時在工作中因為一個變量提升導致出bug。因此Escript6中為我們帶了塊級聲明
码倦,那么什么是塊級聲明呢企孩?
- 只在當前函數(shù)下聲明的變量有效
- 在代碼塊和{ }括號之內(nèi)有效
let聲明
let
聲明和var聲明用法是一樣,都是定義變量袁稽,使用let聲明的變量沒有var那樣的變量提升勿璃,let聲明的變量只在當前作用域中有效。我們來把上面的example重寫一下。
function person(status) {
if (status) {
let value = "蛙人"
} else {
console.log(value) // 報錯
}
console.log(value) // 報錯
}
person(false)
let是塊級作用域补疑,所有外面的語句塊訪問不到歧沪,let是沒有變量提升的,下面我們來演示一下莲组。
console.log(value) // 報錯
let value = "蛙人"
禁止重復聲明
如果在同一個作用域中某個變量已經(jīng)存在诊胞,再次使用let關鍵字聲明的話會報錯。
var value = "蛙人"
let value = "蛙人" // 報錯
// 再來看一下不同作用域的情況
var value = "蛙人" // 全局作用域
if(true) {
let value = "蛙人" // 代碼塊中聲明胁编,毫無影響
}
上面example中厢钧,可以完全看到,只有在相同作用域中重復聲明變量才會報錯嬉橙。
const聲明
ECMAscript6中還提供了const關鍵字聲明早直,const聲明指的是常量,常量就是一旦定義完就不能修改的值市框。還有一點需要注意的是霞扬,常量定義必須初始化值,如果不初始化值就會報錯枫振。
const value = "蛙人"
const age; // 報錯 常量未初始化
const 與 let
const與let也沒什么大不同喻圃,都是塊級作用域,const常量也只會在當前代碼塊內(nèi)有效粪滤,也不能在當前作用域中重復定義相同的變量斧拍,也不存在變量提升。
if (true) {
const name = "蛙人"
}
console.log(name) // 報錯 訪問不到內(nèi)部變量
console.log(value) // 報錯 const聲明的變量也不存在變量提升
const value = "蛙人"
let value = "蛙人"
const value = "蛙人" // 報錯 重復聲明
const聲明對象
雖然const變量不能修改指針杖小,但是可以修改值肆汹,比如我們定義一個對象,我們就可以修改對象里的屬性值予权,但是不可以重寫整個對象昂勉。
const person = {
name: "蛙人",
age: 23
}
person.age = 18 // 沒問題
person = {} // 報錯 不能修改對象指針
暫時死區(qū)
跟var相比,let和const定義變量不會被提升到作用域頂端扫腺,即便是用相對安全的typeof也會出現(xiàn)錯誤岗照。
console.log(typeof value)
let value = "蛙人"
上面example中,console.log(typeof value)
會拋出錯誤是因為用let定義并初始化變量語句是不會執(zhí)行的笆环。此時的value還是處于在JavaScript所謂的暫時死區(qū)(temporal dead zone)
簡稱為TDZ 中攒至,雖然JavaScript沒有明確標準TDZ,但是人們常用它描述let和const定義的變量不會提升躁劣。
我們來說一下TDZ工作原理迫吐,JavaScript引擎在掃描代碼時發(fā)現(xiàn)變量聲明時,如果遇到var
就會將它們提升到當前作用域的頂端习绢,如果遇到let或const
就會將聲明放到TDZ中渠抹,如果訪問TDZ中的變量就會拋出錯誤蝙昙,只有執(zhí)行完TDZ中的變量才會將它移出,然后就可以正常方法梧却。這機制只會在當前作用域生效奇颠。我們來看下不同作用域案例
console.log(typeof value) // "undefined"
if (true) {
let value = "蛙人"
}
上面說的如果變量是let和const聲明的就會被放到TDZ中,前提是只會針對當前作用域內(nèi)有效放航。所以上面代碼中console.log(typeof value)
不會拋出錯誤烈拒,let聲明只會在當前的語句中有效。