var 、let、const的區(qū)別

總結(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)容可以修改

圖片.png
  • const的作用域與let命令相同:只在聲明所在的塊級(jí)作用域內(nèi)有效。
  • const命令聲明的常量也是不提升,同樣存在暫時(shí)性死區(qū),只能在聲明的位置后面使用。
  • const聲明的常量,也與let一樣不可重復(fù)聲明。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容