哈嘍你們好,又見面啦,我依舊是那個可愛的蛙人。java
今天又週五了啊,划水人的一天,開心。安全
話很少說哈,直接摟代碼函數
var 變量提高機制
咱們在全局做用域中或仍是在局部做用域中,使用var
關鍵字聲明的變量,都會被提高到該做用域的最頂部,這就是咱們常說的變量提高。指針
function person(status) { if (status) { var value = "蛙人" } else { console.log(value) // undefined } console.log(value) // undefined } person(false)
上面example中,if
代碼塊中的var聲明的變量就被提高到了函數的頂端,有的小夥伴就會疑惑了,if
代碼塊裏的都沒執行,怎麼會提高到頂端了呢?,這是由於javaScript引擎,在代碼預編譯時,javaScript引擎會自動將全部代碼裏面的var
關鍵字聲明的語句都會提高到當前做用域的頂端, 所以上面的代碼就會被解析爲下面。code
function person(status) { var value; if (status) { value = "蛙人" } else { console.log(value) // undefined } console.log(value) // undefined } person(false)
因爲javaScript存在變量提高,這讓不少開發者初學起來這門語言,還得花很多時間研究變量提高,也有時在工做中由於一個變量提高致使出bug。所以Escript6中爲咱們帶了塊級聲明
,那麼什麼是塊級聲明呢?對象
- 只在當前函數下聲明的變量有效
- 在代碼塊和{ }括號以內有效
let聲明
let
聲明和var聲明用法是同樣,都是定義變量,使用let聲明的變量沒有var那樣的變量提高,let聲明的變量只在當前做用域中有效。咱們來把上面的example重寫一下。ip
function person(status) { if (status) { let value = "蛙人" } else { console.log(value) // 報錯 } console.log(value) // 報錯 } person(false)
let是塊級做用域,全部外面的語句塊訪問不到,let是沒有變量提高的,下面咱們來演示一下。作用域
console.log(value) // 報錯 let value = "蛙人"
禁止重複聲明
若是在同一個做用域中某個變量已經存在,再次使用let關鍵字聲明的話會報錯。開發
var value = "蛙人" let value = "蛙人" // 報錯 // 再來看一下不一樣做用域的狀況 var value = "蛙人" // 全局做用域 if(true) { let value = "蛙人" // 代碼塊中聲明,毫無影響 }
上面example中,能夠徹底看到,只有在相同做用域中重複聲明變量纔會報錯。io
const聲明
ECMAscript6中還提供了const關鍵字聲明,const聲明指的是常量,常量就是一旦定義完就不能修改的值。還有一點須要注意的是,常量定義必須初始化值,若是不初始化值就會報錯。
const value = "蛙人" const age; // 報錯 常量未初始化
const 與 let
const與let也沒什麼大不一樣,都是塊級做用域,const常量也只會在當前代碼塊內有效,也不能在當前做用域中重複定義相同的變量,也不存在變量提高。
if (true) { const name = "蛙人" } console.log(name) // 報錯 訪問不到內部變量
console.log(value) // 報錯 const聲明的變量也不存在變量提高 const value = "蛙人"
let value = "蛙人" const value = "蛙人" // 報錯 重複聲明
const聲明對象
雖然const變量不能修改指針,可是能夠修改值,好比咱們定義一個對象,咱們就能夠修改對象裏的屬性值,可是不能夠重寫整個對象。
const person = { name: "蛙人", age: 23 } person.age = 18 // 沒問題 person = {} // 報錯 不能修改對象指針
暫時死區
跟var相比,let和const定義變量不會被提高到做用域頂端,即使是用相對安全的typeof也會出現錯誤。
console.log(typeof value) let value = "蛙人"
上面example中,console.log(typeof value)
會拋出錯誤是由於用let定義並初始化變量語句是不會執行的。此時的value仍是處於在JavaScript所謂的暫時死區(temporal dead zone)
簡稱爲TDZ 中,雖然JavaScript沒有明確標準TDZ,可是人們經常使用它描述let和const定義的變量不會提高。<br>
咱們來講一下TDZ工做原理,JavaScript引擎在掃描代碼時發現變量聲明時,若是遇到var
就會將它們提高到當前做用域的頂端,若是遇到let或const
就會將聲明放到TDZ中,若是訪問TDZ中的變量就會拋出錯誤,只有執行完TDZ中的變量纔會將它移出,而後就能夠正常方法。這機制只會在當前做用域生效。咱們來看下不一樣做用域案例
console.log(typeof value) // "undefined" if (true) { let value = "蛙人" }
上面說的若是變量是let和const聲明的就會被放到TDZ中,前提是隻會針對當前做用域內有效。因此上面代碼中console.log(typeof value)
不會拋出錯誤,let聲明只會在當前的語句中有效。
var let const 最大的區別
var在全局做用域聲明的變量有一種行爲會掛載在window對象上,它會建立一個新的全局變量做爲全局對象的屬性,這種行爲說不定會覆蓋到window對象上的某個屬性,而let const
聲明的變量則不會有這一行爲。來看下面例子。
var value1 = "張三" let value2 = "李四" const value3 = "王五" console.log(window.value1) // 張三 console.log(window.value2) // undefined console.log(window.value3) // undefined