【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
宣告的變數只能是全域性或整個函式塊的。let
和var
不同之處在於前者是「在編譯時」才被「初始化」。
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.
}
複製程式碼
下面這種var
與 let
合併的宣告方式也會報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;
}
}
複製程式碼
如果你覺得這篇文章對你有幫助,請點贊支援一下哦!