let與const命令
阿新 • • 發佈:2018-11-15
let和var一樣是用來宣告變數的。但是,它與var有很大的不同。
使用let宣告的變數只在其所在的程式碼塊內有效。
if (true) { var a = 1; }
console.log(a); //1
if (true) { let a = 1; }
console.log(a); 報錯
在全域性作用域中,使用let宣告的變數不會是window物件的屬性。
var age = 1;
console.log(window.age) //1
let age = 1;
console.log(window.age) //undefined
let與for迴圈
for (var i = 0; i < 10; i++) { arr[i] = function () { console.log(i) } } arr[0]() //10 arr[9]() //10
由於變數i指向的是同一個,所以for迴圈結束後,數值變成了10,輸出的也就是10
for (let i = 0; i < 10; i++) {
arr[i] = function () {
console.log(i)
}
}
arr[0]() //0
...
arr[9]() //9
當使用了let關鍵字後,每次迴圈都會重新建立i,所以輸出的是0-9
使用let的時候,for的括號內為父作用域,花括號內子作用域,它們之間相互獨立。
for (let i = 0; i < 10; i++) { let i = "a"; console.log(i) //"a" }
可以看到,兩個變數i之間是獨立的,互相不影響。
for (let i = 0; i < 10; i++) {
console.log(i) 報錯
let i = "a";
console.log(i) //"a"
}
需要注意的是,在作用域內使用一個let宣告的變數的時候,必須是在宣告之後使用,否則一律報錯!
所以可以看到,絕不像var那樣,在變數宣告之前使用變數會輸出undefined,這種現象稱之為變數提升。
而let則杜絕了這種現象,告訴我們先宣告,後使用,才是好習慣!
console.log(a)//undefined var a = 1; console.log(a) //報錯 let a = 1;
建立私有作用域
es5:
(function () {
var a = 1;
function fn () {}
})()
console.log(a) 報錯
fn() 報錯
es6:
{
let a = 1;
let fn = function () {};
}
console.log(a) 報錯
fn() 報錯
不過可惜的是es6的方式不能夠有返回值。
使用const宣告變數
const宣告變數的最大特點是,宣告的時候必須立即初始化,宣告過後不可修改,否則報錯!
const name = 1; //正確
const name; //錯誤
const name = 1;
name = 2; //錯誤
const與let宣告的變數一樣,只在其所在的程式碼塊內有效,沒有變數提升,必須先宣告,後使用。在全域性作用域中宣告的變數不屬於window物件的屬性。
需要注意的是,對於引用型別的值,const只能保證其記憶體地址不變,因此在物件上進行一些修改是可行的。
const name = {
a : 1
}
name.a = 2;
console.log(name.a) //2
name = {} 錯誤
如果想要凍結物件,可以使用freeze方法。
const obj = Object.freeze({
name : 1
})
obj.name = 2 //無效 嚴格模式下將報錯
但如果物件中包含有物件型別的值,那麼這個物件內的物件是可變得。
const obj = Object.freeze({
name : 1,
arr : [1]
})
obj.arr.push(1)
console.log(obj.arr) //[1,1]
可以使用遞迴方法徹底凍結物件
let frreezeObj = (obj) => {
//凍結物件
Object.freeze(obj);
//object.keys方法返回obj中所有可列舉的屬性的陣列,然後對陣列進行遍歷
Object.keys(obj).forEach((key, i) => {
//如果是引用型別的話
if (typeof obj[key] === 'object') {
//呼叫自身,將物件凍結
frreezeObj(obj[key]);
}
})
}
let obj = {
arr : [1]
}
frreezeObj(obj);
obj.arr.push(1) //報錯:物件不可拓展