Web前端入門第 56 問:JavaScript 變量聲明 var、let、const 區別
曾經 var 如帝王一般統治過 JS 的變量聲明,直到后來大佬們實在是忍不了 var 那稀爛的聲明規則,便引入了 let 和 const 這兩大刀斧手,var 被輕輕松松的斬落馬下,如今,再難看見 var 的身影。
變量聲明
在 JS 中,所有變量都可以用 var、let 和 const 這三個關鍵字聲明。
// 字符串
var name1 = '前端路引';
let name2 = '前端路引';
const name3 = '前端路引';
// 數字
var age1 = 18;
let age2 = 18;
const age3 = 18;
// 布爾值
var isDev1 = true;
let isDev2 = true;
const isDev3 = true;
// 空值
var null1 = null;
let null2 = null;
const null3 = null;
// 數組
var arr1 = [1, 2, 3];
let arr2 = [1, 2, 3];
const arr3 = [1, 2, 3];
// 對象
var obj1 = {};
let obj2 = {};
const obj3 = {};
// 函數
var fn1 = function () {
console.log('前端路引');
}
let fn2 = function () {};
const fn3 = function () {};
以上的各種聲明方法都是有效的,JS 語法也沒強制要求必須用某個關鍵字聲明變量。
區別
它們之間有哪些恩恩怨怨,為什么會在新的語法中引入 let 和 const 來取代 var 呢?
作用域
var 申明的變量,擁有函數作用域,在整個函數體內部都能訪問。
let 和 const 申明的變量是塊級作用域,出了代碼塊(就是 {} 包裹的代碼片段)就不可以再訪問了。
function funcScope() {
if (true) {
var a = 1; // 函數作用域
let b = 2; // 塊級作用域
const c = 3; // 塊級作用域
}
console.log(a); // 1(var 穿透了 if 代碼塊)
console.log(b); // ReferenceError: b is not defined
console.log(c); // ReferenceError: c is not defined
}
變量申明提升
var 申明的變量,不論在哪個位置申明,都會提升到作用域頂部。
let 和 const 申明存在 暫時性死區(TDZ),這些名詞道道記不住也罷,反正您只要知道在申明之前使用會報錯就對了。
console.log(x); // undefined(變量提升)
var x = 10;
console.log(x); // 10
console.log(y); // ReferenceError: y is not defined(暫時性死區)
let y = 20;
var 申明的變量,在申明之前使用會獲取 undefined,這就是所謂的 變量申明提升。
重復聲明
var 允許同一個變量重復聲明。
let 和 const 禁止重復聲明。
var a = 1;
var a = 2; // 允許
console.log(a) // 2
let b = 1;
let b = 2; // SyntaxError: Identifier 'b' has already been declared
const c = 1;
const c = 2; // SyntaxError: Identifier 'c' has already been declared
let 和 const 重復聲明同一個變量,會報語法錯誤。
全局作用域下的行為
如果在全局作用域中使用 var 申明一個變量,那么這變量會變成全局對象(如 window)的一個屬性。
let 和 const 則不會綁定到全局對象。
什么是全局作用域?比如新建一個 a.js,使用 <script src="a.js"></script> 引入這個 JS 文件到 html 頁面中,那么這個 JS 文件最外層就稱之為全局作用域。
新建一個 test.html,引入 a.js:
<script src="a.js"></script>
新建一個 a.js:
// 全局作用域
var globalVar = 1;
console.log(window.globalVar); // 1
let globalLet = 2;
console.log(window.globalLet); // undefined
function test () {
// 函數作用域
};
{
// 塊級作用域
}
可變性
var 和 let 聲明的變量可以重新賦值。
const 聲明的是常量,必須初始化且不可重新賦值(但對象/數組的內容可修改)。
var str = '前端路引';
str = 'web3dev'; // 允許修改變量
let num = 1;
num = 2; // 允許修改變量
const PI = 3.14;
PI = 3; // TypeError: Assignment to constant variable.(不可重新賦值)
const obj = { a: 1 };
obj.a = 2; // 允許(修改屬性)
obj = {}; // TypeError: Assignment to constant variable.(不可重新賦值)
為什么 const 申明的數組和對象可以修改?
這就涉及到 引用 這個概念了,可以理解為 數組 和 對象 就像現實中的房子。const 申明就像給房子打上了標簽貼,擁有了這個房子的使用權,但這房子不止 const 一個擁有者,房子的主人還能對房子進行室內裝修改變。const 的標簽貼只能使用一次,要想把這標簽再貼在另一座房子,那么就行不通了!!
循環
var 申明的變量會泄露到循環體外部。
let 僅作用于循環體內部。
for (var i = 0; i < 3; i++) {}
console.log(i); // 3
for (let j = 0; j < 3; j++) {}
console.log(j); // ReferenceError: j is not defined
let 解決異步回調問題:
// var 的問題
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i)); // 輸出 3, 3, 3
}
// let 的解決方案
for (let j = 0; j < 3; j++) {
setTimeout(() => console.log(j)); // 輸出 0, 1, 2
}
寫在最后
最佳實踐推薦:所有變量聲明優先考慮使用 const ,如果確定變量需要修改再使用 let。
果您的代碼確實需要兼容 2017 年之前的瀏覽器,那么使用 var 吧,別考慮 const 和 let 了。當然也可以使用 babel 等編譯器,將 const 和 let 轉換成 var 兼容低版本瀏覽器。

浙公網安備 33010602011771號