1. 程式人生 > 前端設計 >【JS】JavaScript語句和宣告之let,const

【JS】JavaScript語句和宣告之let,const

let 語句宣告一個塊級作用域的本地變數,且可選地將其初始化為一個值。

const 語句宣告的常量塊級作用域,與使用let語句定義的變數相似。常量的值不能通過重新賦值來改變,且不能重新宣告

1.語法

let 變數名1 [= 變數值1] [,變數名2 [= 變數值2]] [,...,變數名N [= 變數值N]];

  • 變數名1,變數名2,...,變數名N:變數名。 必須是合法的識別符號。
  • 變數值1,變數值2,...,變數值N:變數的初始值。 可以是任意合法的表示式。

const name1 = value1 [,name2 = value2 [,... [,nameN = valueN]]];

  • name1,name2,...,nameN:常量名稱。 可以是任意合法的識別符號。
  • value1,value2,...,valueN:常量值。 可以是任意合法的表示式。

2.描述

let宣告的變數、語句或表示式都被限制在塊級作用域。與var關鍵字不同的是,var宣告的變數只能是全域性或整個函式塊的。letvar不同之處在於前者是在編譯時才被初始化

const宣告建立一個常量,其作用域可以是全域性或本地宣告的塊。 與var變數不同,全域性常量不會變為window物件的屬性。需要一個常數的初始化器,即必須在宣告時指定它的值(這是有道理的,因為以後不能更改)。

const

宣告建立一個值的只讀引用。但這並不意味著它所持有的值是不可變的,只是變數識別符號不能重新分配。比如,在引用內容是物件的情況下,這就意味著可以改變物件的內容(如,其引數)。

const宣告建立常量不能和它所在作用域內的其他變數或函式擁有相同的名稱

const一樣,let也不會在全域性宣告時(在最頂部的範圍)建立window物件的屬性。

3.常量的特性

注意: 常量在宣告時可以使用大小寫,但通常情況下全部用大寫字母

  • 不能重新賦值
  • 不能重新宣告
const MYFAVNUM = 7;  // 定義常量MYFAVNUM 並賦值7
MYFAVNUM = 20;   // 報錯(不能重新賦值)
console.log("my favorite number is: " + MYFAVNUM ); // 輸出 7 const MYFAVNUM = 20; //報錯(不能重新宣告) var MYFAVNUM = 20; // MYFAVNUM 保留給上面的常量,這個操作會失敗 let MYFAVNUM = 20; // 也會報錯 // 注意:塊範圍的性質很重要 if (MYFAVNUM === 7) { let MYFAVNUM = 20;// 沒問題,並且建立了一個塊作用域變數 MYFAVNUM console.log('my favorite number is ' + MYFAVNUM ); // MYFAVNUM 現在為 20 var MYFAVNUM = 20; //報錯(這被提升到全域性上下文並引發錯誤) } console.log("my favorite number is " + MYFAVNUM ); // MYFAVNUM 依舊為 7
複製程式碼
  • 常量需要一個初始值
const FUN;  // 報錯Uncaught SyntaxError: Missing initializer in const declaration(常量要求一個初始值)
複製程式碼
  • 常量可以定義成物件
const MY_OBJECT = {"key": "value"};
MY_OBJECT = {"OTHER_KEY": "value"}; // 報錯(重寫物件和上面一樣會失敗)
複製程式碼
  • 物件屬性並不在保護的範圍內,下面這個宣告會成功執行
MY_OBJECT.key = "otherValue";
複製程式碼
  • 也可以用來定義陣列
const MY_ARRAY = [];
MY_ARRAY.push('A'); // ["A"] // 可以向陣列填充資料
MY_ARRAY = ['B'];  // 但,將一個新陣列賦給變數會引發錯誤!報錯。
複製程式碼

4.作用域規則

let宣告的變數只在其宣告的塊或子塊中可用,這一點,與var相似。二者之間最主要的區別在於var宣告變數的作用域是整個封閉函式。舉例子如下:

function varTest() {
  var a = 1;
  {
    var a = 2;       // 同樣的變數!
    console.log(a);  // 2
  }
  console.log(a);    // 2
}
varTest();
複製程式碼
function letTest() {
  let a = 1;
  {
    let a = 2;       // 不同樣的變數!
    console.log(a);  // 2
  }
  console.log(a);    // 1
}
letTest();
複製程式碼

在程式碼和方法的最頂端,let不像var一樣,let不會在全域性物件裡新建一個屬性。即位於函式或程式碼頂部的var宣告會給全域性物件新增屬性,而let不會。比如:

var a = 'global';
let b = 'global';
console.log(window.a);  // "global"
console.log(window.b);  // "undefined"
複製程式碼

5. 模仿私有成員

在處理建構函式時,可通過let宣告而不是閉包來建立一個或多個私有成員。

var Thing; //定義全域性變數Thing
{
  let privateScope = new WeakMap();
  let counter = 0;
  Thing = function() {  //全域性變數Thing指向函式物件
    this.someProperty = 'fun';
    privateScope.set(this,{
      hidden: ++counter,    });
  };

  Thing.prototype.showPublic = function() {
    return this.someProperty;
  };
  Thing.prototype.showPrivate = function() {
    return privateScope.get(this).hidden;
  };
}
console.log(typeof privateScope); // "undefined",privateScope不存在全域性作用域

var thing = new Thing();
console.log(thing);  // Thing {someProperty: "fun"}
thing.showPublic();  // "fun"
thing.showPrivate(); // 1
複製程式碼

可用var建立和閉包具有相同隱私模式的區域性變數,但它們需要函式作用域(通常是模組模式中的IIFE),而不僅僅是上面示例中的塊作用域。

6.重複宣告

  • 在同一個函式作用域塊作用域中重複宣告同一個變數會引起SyntaxError(語法錯誤)。
if (a) {
  let b;
  let b; //報錯:Uncaught SyntaxError: Identifier 'b' has already been declared.
}
複製程式碼

下面這種varlet合併的宣告方式也會報SyntaxError錯誤,因為var會將變數提升至塊頂部, 這就導致隱式地重複宣告變數。

let a = 1;
{
  var a = 2; // 報錯 Uncaught SyntaxError: Identifier 'a' has already been declared
}
複製程式碼
  • switch語句中只有一個塊,可能因此而遇到錯誤。
let a = 1;
switch(a) {
  case 0:
    let b;
    break;
  case 1:
    let b;  //報錯:Uncaught SyntaxError: Identifier 'b' has already been declared
    break;
}
複製程式碼

但,需要特別指出的是,一個巢狀在case 子句中的塊會建立一個新的塊作用域的詞法環境,就不會產生上訴重複宣告的錯誤。如下:

let a = 1;
switch(a) {
  case 0: {  //新的塊級作用域
    let b;
    break;
  }  
  case 1: { //新的塊級作用域
    let b;
    break;
  }
}
複製程式碼

如果你覺得這篇文章對你有幫助,請點贊支援一下哦!