在ES6以前,JS是沒有塊級做用域這個概念的,只有全局做用域和函數內的局部做用域bash
咱們都是知道在 ES6 之前,var 關鍵字聲明變量。不管聲明在何處,都會被視爲聲明在函數的最頂部(不在函數內即在全局做用域的最頂部)。這就是變量提高例如:閉包
function fn() {
if(false) {
var aa = "hello"
}else {
console.log(aa)
}
}
fn()//undefined複製代碼
以上的代碼其實是:函數
function fn() {
var aa //變量提高
if(false) {
aa = "hello"
}else {
//此處訪問aa的值爲undefined
console.log(aa)
}
}
fn()//undefined
複製代碼
因此不管如何 aa 都會被建立聲明ui
與var命令的對比,以及let的一些特性:spa
1.let命令聲明一個塊級做用域內的變量語句或表達式,並可選地爲其初始化一個值。指針
如下方式都是合法的:code
let a
let b = 666
let c = 1, d = 'string', e = {}
let f = function () {}
let g = true ? 'true' : 'false'複製代碼
2.let命令只在塊級做用域有效,在代碼塊以外引用會報錯,同時不能重複聲明。對象
{
let a = 1
}
console.log(a) // ReferenceError a is not defined複製代碼
function foo () {
const a = 4
let a = 1
}
foo() //SyntaxError: Identifier 'a' has already been declared複製代碼
for(var i = 0; i < 5; i++){
}
console.log(i) // 5
for(let i = 0; i < 5; i++){
}
console.log(i) //ReferenceError: i is not defined
複製代碼
3.let不存在變量提高內存
console.log(a) // undefined
console.log(b) // ReferenceError: b is not defined
var a = 1
let b = 1
複製代碼
4作用域
由於let不存在變量提高所以ES6中的let聲明變量時,會在此區域內造成暫時性死區(暫時性死區就是在這個區塊中的變量未聲明以前,對該區塊中的變量的一切調用都會報錯),在該區域內不容許有任何形勢聲明出來的相同變量,因此,let聲明的變量只能在該區域中只出現一次,不能有重複的
a = 1
let a = 2
//ReferenceError: a is not defined
複製代碼
a = 1
{let a = 2}
// 以上代碼不會報錯,由於聲明變量的區塊不一複製代碼
for(var i = 0; i < 5; i++){
setTimeout(function(){
console.log(i)
}, 1000)
}
複製代碼
1.ES6以前的解決辦法,使用一個變量對 i 的值進行暫存
for(var i = 0; i < 5; i++){
(function(e){
setTimeout(function(){
console.log(e)
}, 1000)
})(i)
}
複製代碼
2.出現let後的解決辦法
for(let i = 0; i < 5; i++){
setTimeout(function(){
console.log(i)
}, 1000)
}複製代碼
關於for循環做用域的問題
在for循環中其實是有兩個做用域的,條件設置的圓括號()內是一個父做用域,而代碼塊大括號{}中是一個子做用域,好比下面代碼能夠進行區分
for(let i = 0; i < 5; i++){
let i = 8
console.log(i)
}
// 輸出結果是5個8複製代碼
與let命令的用法相似,const命令也是用來聲明一個變量,同時也只能在聲明的塊級做用域中進行使用,它與C#中的const做用相同,只能賦一次值,不能夠修改, 初始化時必須賦值
const命令的特性
1.聲明的時候就必須立刻初始化,不然報錯
以下代碼:
const a; //SyntaxError: Missing initializer in const declaration
複製代碼
2.聲明的值不能改變,不能從新進行賦值
const a = 10;
const a = 12 //SyntaxError: Identifier 'a' has already been declared
複製代碼
3.與let同樣不存在變量提高
console.log(a) //ReferenceError: a is not defined
const a = 12
複製代碼
4.與let同樣不可重複進行聲明
const a = 1
var a = 1 // SyntaxError: Identifier 'a' has already been declared複製代碼
注意點
1.const聲明的變量的值不能改變實質上是變量指向的內存地址不能改變,所以會有如下兩種狀況
const a = {b:1}
console.log(a.b) // 1
a.b = 2
console.log(a.b) // 2
複製代碼
const a = Object.freeze({b:1})
console.log(a.b) // 1
a.b = 2
console.log(a.b) // 1複製代碼