JavaScript var、let、const
1. 概述
1.1 說明
在ES5 聲明變量的方法:var
命令和function
命令。
在ES6 聲明變量的方法:var
命令、function
命令、let命令、const
命令、import
命令、class
命令。
以下內容主要是對 let 、var 、const 命令的理解與記錄。
1.2 let 命令
1.2.1 let 說明
let命令的聲明變量用法類似於var,如 let a =10;(聲明了一個變量:變量名為a,值為10)。但let所聲明的變量,只在let命令所在的代碼塊內有效,即let用於聲明一個塊級作用域的變量。
以下代碼解析:在函數test中的if代碼塊中使用let進行聲明變量;在if代碼快中調用所聲明變量可以獲取正確的值,而在if代碼塊外調用所聲明變量則會報錯。
function test() { if (true) { let x = 1; console.log(x); // 1 } console.log(x); // Uncaught ReferenceError: x is not defined } test();
for循環的計數器
for (let x = 0; x < 5; x++) { setTimeout(function() { console.log(x);// 0 1 2 3 4 }, 100); } console.log(x);// Uncaught ReferenceError: x is not defined
1.2.1 let 特性
詳見 var 與 let 的對比。
- 塊級作用域
- 不允許在相同作用域內,重復聲明同一個變量
- 暫時性死區
1.3 var 命令
1.3.1 var 說明
使用var進行聲明變量。var a =10;(聲明了一個變量:變量名為a,值為10)。在ES6之前,JavaScript沒有塊級作用域,只有全局作用域和函數作用域。變量提升即是將變量聲明提升到它所在作用域的最開始的部分。
//全局作用域 console.log(global); // undefined var global = ‘global‘; console.log(global); // global //函數作用域 function test () { console.log(x); // undefined var x = 1; console.log(x); // 1 } test();// 調用函數
以上代碼中var聲明的變量在不同作用域中進行了變量提升(在當前作用域下,在聲明變量之前進行了調用,返回了變量值為undefined)。以上代碼等同於以下代碼:
var global; // 變量提升,全局作用域範圍內,此時只是聲明,並沒有賦值 console.log(global); // undefined global = ‘global‘; // 此時才賦值 console.log(global); // global function test () { var x; // 變量提升,函數作用域範圍內 console.log(x);// undefined x = 1;// 此時才賦值 console.log(x);// 1 } test();
for循環的計數器
for (var x = 0; x < 5; x++) { console.log(x); // 0 1 2 3 4 setTimeout(function() { console.log(x); // 5 5 5 5 5 }, 100); } console.log("***************"); console.log(x);// 5
1.3.2 省略 var
在javascript中,若省略var關鍵字而直接賦值,那麽這個變量為全局變量,哪怕是在function裏定義的。
function a() { x = 2; } function b() { console.log(x);// 2 } a(); b();
1.4 let 與 var
- 作用域的區別
var : 沒有塊級作用域,因為變量提升的特性,其聲明變量的作用域為整個函數或全局範圍。
let : 擁有塊級作用域的特性,其聲明的變量作用域範圍從聲明處一直到當前塊級語句({}包含)的結尾【或一直延伸到函數結尾(在函數內)或全局結尾】。
function testVar() { if (true) { // 變量提升 console.log(x); // undefined var x = 1; console.log(x); // 1 } // 作用域在整個函數作用域中 console.log(x); // 1 } function testLet() { if (true) { // 不存在變量提升 console.log(y); // Uncaught ReferenceError: y is not defined let y = 1; console.log(y); // 1 } // 作用域僅在if語句塊中 console.log(y); // Uncaught ReferenceError: y is not defined } testVar(); testLet();
- 重復聲明
var : 允許在相同作用域內,重復聲明同一個變量。
let : 不允許在相同作用域內,重復聲明同一個變量。
function test() { var x=1; var x=2; var x=3; console.log(x);//3 let y=1; let y=2; console.log(y);//Uncaught SyntaxError: Identifier ‘y‘ has already been declared } test();
- 頂層對象的屬性(window)
var : 在全局作用域聲明的變量,會作為widnow對象的成員。
let : 在全局作用域聲明的變量,不會作為window對象的成員。
var x = 1; let y = 1; //var聲明的變量附加到window對象上 console.log(window.x); // 1 //let聲明的變量沒有附加到window對象上 console.log(window.y); // undefined
- 暫時性死區
var : 不存在暫時性死區。
let : 存在暫時性死區【在代碼塊內,使用let
命令聲明變量之前,該變量都是不可用的。這在語法上,稱為“暫時性死區”(temporal dead zone,簡稱 TDZ)】。
var a = 123; if (true) { a = ‘abc‘; console.log(a);// abc var a; console.log(a);// abc } var x = 123; if (true) { x = ‘abc‘; // Uncaught ReferenceError: x is not defined let x; }
備註:ES6 明確規定,如果區塊中存在let
和const
命令,這個區塊對這些命令聲明的變量,從一開始就形成了封閉作用域。凡是在聲明之前就使用這些變量,就會報錯
1.5 const 命令
1.5.1 const 說明
使用const進行聲明變量所定義的是一個只讀的常量,一旦聲明,常量的值就不能改變。const a =10;(聲明了一個常量變量:變量名為a,值為10)。
const x = 1; x = 2; // Uncaught TypeError: Assignment to constant variable
1.5.2 const 特性
- 塊級作用域(與let命令相同)
- 不允許在相同作用域內,重復聲明同一個變量(與let命令相同)
- 暫時性死區(與let命令相同)
- 在全局作用域聲明的變量,不會作為window對象的成員
- 當用const聲明的常量為值類型(e.g. String、Number)時,修改此常量的值會報錯;但當聲明的常量為引用類型(e.g. Array、Object)時,只可以修改此常量的成員
// 1.const聲明一個數組 const x = [1, 2, 3]; console.log(x); // => [1, 2, 3] x[0] = "a"; // 修改數組的第一個元素的值 console.log(x); // [‘a‘, 2, 3] // 2.const聲明一個對象 const obj = {}; obj.name = ‘objName‘; console.log(obj.name); // objName
JavaScript var、let、const