let
let聲明的變量僅在塊級作用域內(nèi)有效
var a = [];
for(let i = 0;i<10;i++){
a[i] = function(){
console.log(i);
};
}
a[6]();//6
上面代碼中绪撵,變量i是let聲明的,當前的i只在本輪循環(huán)有效墩莫,所以每一次循環(huán)的i其實都是一個新的變量,所以最后輸出的是6逞敷。你可能會問狂秦,如果每一輪循環(huán)的變量i都是重新聲明的,那它怎么知道上一輪循環(huán)的值推捐,從而計算出本輪循環(huán)的值裂问?這是因為 JavaScript 引擎內(nèi)部會記住上一輪循環(huán)的值,初始化本輪的變量i時牛柒,就在上一輪循環(huán)的基礎(chǔ)上進行計算堪簿。
另外,for循環(huán)還有一個特別之處皮壁,就是設(shè)置循環(huán)變量的那部分是一個父作用域椭更,而循環(huán)體內(nèi)部是一個單獨的子作用域。
for (let i = 0; i < 3; i++) {
let i = 'abc';
console.log(i);
}
// abc
// abc
// abc
不存在變量提升
// var 的情況
console.log(foo); // 輸出undefined
var foo = 2;
// let 的情況
console.log(bar); // 報錯ReferenceError
let bar = 2;
暫時性死區(qū)
只要塊級作用域內(nèi)存在let命令蛾魄,它所聲明的變量就“綁定”(binding)這個區(qū)域虑瀑,不再受外部的影響湿滓。
var tmp = 123;
if (true) {
tmp = 'abc'; // ReferenceError
let tmp;
}
“暫時性死區(qū)”也意味著typeof不再是一個百分之百安全的操作。
不允許重復(fù)聲明
function func() {
let a = 10;
var a = 1;
}
// 報錯
function func() {
let a = 10;
let a = 1;
}
為什么需要塊級作用域舌狗?
第一:內(nèi)層變量不會覆蓋外層變量
第二:用來計數(shù)的循環(huán)變量泄露為全局變量
const
const聲明一個只讀的常量叽奥。一旦聲明,常量就不能改變把夸。這意味著,const一旦聲明變量铭污,就必須立即初始化恋日,不能留到以后賦值
const實際上保證的,并不是變量的值不得改動嘹狞,而是變量指向的那個內(nèi)存地址不得改動岂膳。對于簡單類型的數(shù)據(jù)(數(shù)值、字符串磅网、布爾值)谈截,值就保存在變量指向的那個內(nèi)存地址,因此等同于常量涧偷。但對于復(fù)合類型的數(shù)據(jù)(主要是對象和數(shù)組)簸喂,變量指向的內(nèi)存地址,保存的只是一個指針燎潮,const只能保證這個指針是固定的喻鳄,至于它指向的數(shù)據(jù)結(jié)構(gòu)是不是可變的,就完全不能控制了确封。因此除呵,將一個對象聲明為常量必須非常小心。如果真的想將對象凍結(jié)爪喘,應(yīng)該使用Object.freeze方法颜曾。
const foo = Object.freeze({});
// 常規(guī)模式時,下面一行不起作用秉剑;
// 嚴格模式時泛豪,該行會報錯
foo.prop = 123;