總結(jié)于——阮一峰老師ECMAScript6入門
js變量聲明的方式:var、let、const
let 和const是es6新出的聲明方式
在前一篇變量提升的博客中,我們知道使用var聲明的變量是全局的。存在變量提升
let
1.作用域只在他所在的代碼塊
一個(gè) {} 可以看作一個(gè)作用域
{
let a=2
var b=3
}
console.log(a) //報(bào)錯(cuò),a is not defined
(很適合用在for中)
for(t=0;t<5;t++){
console.log(t)
}
console.log(t) // 5
for(let t=0;t<5;t++){
let t = "abc"
console.log(t) // "abc"
}
console.log(t) //報(bào)錯(cuò),t is not defined
在作用域之外的 t 不能被訪問。從上面也看出for的特別之處,就是設(shè)置循環(huán)變量的那部分是一個(gè)父作用域,而循環(huán)體內(nèi)部是一個(gè)單獨(dú)的子作用域。
2.let不允許重復(fù)聲明
let不允許在相同作用域內(nèi),重復(fù)聲明同一個(gè)變量。
// 報(bào)錯(cuò)
function func() {
let a = 10;
var a = 1;
}
// 報(bào)錯(cuò)
function func() {
let a = 10;
let a = 1;
}
因此,不能在函數(shù)內(nèi)部重新聲明參數(shù)。這是因?yàn)閖s中形參也會(huì)出現(xiàn)在其執(zhí)行上下文中
function func(arg) {
let arg;
}
func() // 報(bào)錯(cuò)
function func(arg) {
{
let arg;
}
}
func() // 不報(bào)錯(cuò)
3.不存在變量提升
4.脫離頂層作用域
在最外層作用域中使用 let | const | class 聲明的變量,將不會(huì)綁定在頂層作用域 window 或是 global
var a = 1;
// 或者采用通用方法,寫成 this.a
window.a // 1
let b = 1;
window.b // undefined
5.暫時(shí)性死區(qū)
ES6 明確規(guī)定,如果區(qū)塊中存在let和const命令,這個(gè)區(qū)塊對(duì)這些命令聲明的變量,從一開始就形成了封閉作用域。凡是在聲明之前就使用這些變量,就會(huì)報(bào)錯(cuò)。
暫時(shí)性死區(qū)的本質(zhì):只要一進(jìn)入當(dāng)前作用域,所要使用的變量就已經(jīng)存在了,但是不可獲取,只有等到聲明變量的那一行代碼出現(xiàn),才可以獲取和使用該變量。
if (true) {
// TDZ開始
tmp = 'abc'; // ReferenceError
console.log(tmp); // ReferenceError
let tmp; // TDZ結(jié)束
console.log(tmp); // undefined
tmp = 123;
console.log(tmp); // 123
}
隱秘的死區(qū)(謹(jǐn)防筆試的陷阱)
function bar(x = y, y = 2) {
return [x, y];
}
bar(); // 報(bào)錯(cuò)
報(bào)錯(cuò)原因,y沒有被定義,但是卻被x使用了。
再看
function foo(arg1=arg2,arg2){
console.log(`${arg1},${arg2}`)
}
foo(null,'arg2') //null,arg2
foo(undefined,'arg2') //報(bào)錯(cuò),arg2 is undefined
這里涉及undefined和null的區(qū)別
// 不報(bào)錯(cuò)
var x = x;
// 報(bào)錯(cuò)
let x = x;
// ReferenceError: x is not defined
ES6 規(guī)定暫時(shí)性死區(qū)和let、const語句不出現(xiàn)變量提升,主要是為了減少運(yùn)行時(shí)錯(cuò)誤,防止在變量聲明前就使用這個(gè)變量,從而導(dǎo)致意料之外的行為。
let的以上特性,為JavaScript 新增了塊級(jí)作用域。
(沒有塊級(jí)作用域,函數(shù)內(nèi)部的變量可能會(huì)覆蓋外部變量。用來計(jì)數(shù)的循環(huán)變量暴露為全局變量,污染了全局環(huán)境……)
塊級(jí)作用域的出現(xiàn),實(shí)際上使得獲得廣泛應(yīng)用的立即執(zhí)行函數(shù)表達(dá)式(IIFE)不再必要了:
// IIFE寫法,以前這樣寫外部訪問不到a
(function f(){
var a=2
}())
console.log(a) // 報(bào)錯(cuò) a is not defined
// 塊級(jí)作用域?qū)懛?{
let a = 2;
...
}
- 塊級(jí)作用域允許互相嵌套
- 外層作用域不能訪問內(nèi)層變量
- 不同層級(jí)作用域可以定義同名變量
- es6允許在塊級(jí)作用域下聲明函數(shù),在塊級(jí)作用域外不可引用
if 語句也有一個(gè)塊級(jí)作用域,凡有{ }者都有塊級(jí)作用域
- ES6 的塊級(jí)作用域必須有大括號(hào){},如果沒有大括號(hào),JavaScript 引擎就認(rèn)為不存在塊級(jí)作用域。
const
- const聲明一個(gè)只讀的常量。一旦聲明,常量的值就不能改變。所以const一旦聲明變量,就必須立即初始化,不能留到以后賦值。
只聲明,不賦值,會(huì)報(bào)錯(cuò)(注意!var,let只會(huì)報(bào)undefined)
不能重新賦值const 定義的值,但是可以修改const聲明的對(duì)象類型。(只能修改,不能重新賦值)
為什么使用const聲明的基本類型變量不能被修改,而復(fù)雜類型變量就可以?
因?yàn)閏onst保存的是指向數(shù)組或?qū)ο蟮闹羔?。?duì)于基本類型值,使用const聲明的變量是不可以被修改的。但是對(duì)于對(duì)象,指針依然不能修改,但是指針指向內(nèi)容可以修改

- const的作用域與let命令相同:只在聲明所在的塊級(jí)作用域內(nèi)有效。
- const命令聲明的常量也是不提升,同樣存在暫時(shí)性死區(qū),只能在聲明的位置后面使用。
- const聲明的常量,也與let一樣不可重復(fù)聲明。