var let cost
var 宣告提升
使用 var 時,下面的程式碼不會報錯。這是因為使用這個關鍵字宣告的變數會自動提升到函式作用域
頂部:
function foo() {
console.log(age);
var age = 26;
}
foo(); // undefined
之所以不會報錯,是因為 ECMAScript 執行時把它看成等價於如下程式碼:
`function foo() {
var age;
console.log(age);
age = 26;
}
foo(); // undefined
這就是所謂的“提升”(hoist),也就是把所有變數宣告都拉到函式作用域的頂部。此外,反覆多次
使用 var 宣告同一個變數也沒有問題:
function foo() {
var age = 16;
var age = 26;
var age = 36;
console.log(age);
}
foo(); // 36
let 宣告
let 跟 var 的作用差不多,但有著非常重要的區別。最明顯的區別是,let 宣告的範圍是塊作用域,而 var 宣告的範圍是函式作用域。
if (true) {
var name = 'Matt';
console.log(name); // Matt
}
console.log(name); // Matt
if (true) {
let age = 26;
console.log(age); // 26
}
console.log(age); // ReferenceError: age 沒有定義
let 也不允許同一個塊作用域中出現冗餘宣告。這樣會導致報錯:
var name;
var name;
let age;
let age; // SyntaxError;識別符號 age 已經宣告過了
對宣告冗餘報錯不會因混用 let 和 var 而受影響。這兩個關鍵字宣告的並不是不同型別的變數, 它們只是指出變數在相關作用域如何存在。
var name;
let name; // SyntaxError
let age;
var age; // SyntaxError
let 與 var 的另一個重要的區別,就是 let 宣告的變數不會在作用域中被提升。
在解析程式碼時,JavaScript 引擎也會注意出現在塊後面的 let 宣告,只不過在此之前不能以任何方式來引用未宣告的變數。在 let 宣告之前的執行瞬間被稱為“暫時性死區”(temporal dead zone),在此階段引用任何後面才宣告的變數都會丟擲 ReferenceError。
// name 會被提升
console.log(name); // undefined
var name = 'Matt';
// age 不會被提升
console.log(age); // ReferenceError:age 沒有定義
let age = 26;
全域性宣告
與 var 關鍵字不同,使用 let 在全域性作用域中宣告的變數不會成為 window 物件的屬性(var 宣告的變數則會)。
var name = 'Matt';
console.log(window.name); // 'Matt'
let age = 26;
console.log(window.age); // undefined
條件宣告
對於 let 這個新的 ES6 宣告關鍵字,不能依賴條件宣告模式
<script>
let name = 'Nicholas';
let age = 36;
</script>
<script>
// 假設指令碼不確定頁面中是否已經宣告瞭同名變數
// 那它可以假設還沒有宣告過
if (typeof name === 'undefined') {
let name;
}
// name 被限制在 if {} 塊的作用域內
// 因此這個賦值形同全域性賦值
name = 'Matt';
try {
console.log(age); // 如果 age 沒有宣告過,則會報錯
}
catch(error) {
let age;
}
// age 被限制在 catch {}塊的作用域內
// 因此這個賦值形同全域性賦值
age = 26;
</script>
for 迴圈中的 let 宣告
let 出現之前,for 迴圈定義的迭代變數會滲透到迴圈體外部:
for (var i = 0; i < 5; ++i) {
// 迴圈邏輯
}
console.log(i); // 5
改成使用 let 之後,這個問題就消失了,因為迭代變數的作用域僅限於 for 迴圈塊內部:
for (let i = 0; i < 5; ++i) {
// 迴圈邏輯
}
console.log(i); // ReferenceError: i 沒有定義
在使用 var 的時候,最常見的問題就是對迭代變數的奇特宣告和修改:
for (var i = 0; i < 5; ++i) {
setTimeout(() => console.log(i), 0)
}
// 你可能以為會輸出 0、1、2、3、4
// 實際上會輸出 5、5、5、5、5
之所以會這樣,是因為在退出迴圈時,迭代變數儲存的是導致迴圈退出的值:5。在之後執行超時邏輯時,所有的 i 都是同一個變數,因而輸出的都是同一個最終值。
而在使用 let 宣告迭代變數時,JavaScript 引擎在後臺會為每個迭代迴圈宣告一個新的迭代變數。每個 setTimeout 引用的都是不同的變數例項,所以 console.log 輸出的是我們期望的值,也就是迴圈執行過程中每個迭代變數的值。
for (let i = 0; i < 5; ++i) {
setTimeout(() => console.log(i), 0)
}
// 會輸出 0、1、2、3、4
因為對於 let 來說,他會建立一個塊級作用域,相當於
{ // 形成塊級作用域
let i = 0
{
let ii = i
setTimeout( function timer() {
console.log( ii );
}, 0 );
}
i++
{
let ii = i
}
i++
{
let ii = i
}
...
}
const 的行為與 let 基本相同,唯一一個重要的區別是用它宣告變數時必須同時初始化變數,且嘗試修改 const 宣告的變數會導致執行時錯誤。
const age = 26;
age = 36; // TypeError: 給常量賦值
// const 也不允許重複宣告
const name = 'Matt';
const name = 'Nicholas'; // SyntaxError
// const 宣告的作用域也是塊
const name = 'Matt';
if (true) {
const name = 'Nicholas';
}
console.log(name); // Matt
const 宣告的限制只適用於它指向的變數的引用。換句話說,如果 const 變數引用的是一個物件,
那麼修改這個物件內部的屬性並不違反 const 的限制。
const person = {};
person.name = 'Matt'; // ok
JavaScript 引擎會為 for 迴圈中的 let 宣告分別建立獨立的變數例項,雖然 const 變數跟 let 變
量很相似,但是不能用 const 來宣告迭代變數(因為迭代變數會自增):
for (const i = 0; i < 10; ++i) {} // TypeError:給常量賦值
相關文章
- let var與const
- var let const區別
- let const var 區別
- let,const,var區別
- 詳解 let 和 var
- var、const、let 的區別
- var 和 let 的區別
- let與var的區別
- TypeScript let與var的區別TypeScript
- 1.變數:var,let,const變數
- var和let/const的區別
- var,let和const深入解析(一)
- ES6之var、let、const
- var、let和const的區別
- var、let和const的知識點
- 教你理解let和var的區別
- 淺談let和var的區別
- JavaScript中let、const、var 的區別JavaScript
- js中 let 與 var 的區別JS
- When to use var vs let vs const in JavaScriptJavaScript
- 從var 到 let,JS 用了整整18年!JS
- JavaScript中的var、let 及 const 區別JavaScript
- JavaScript中var與let的異同點JavaScript
- var與let宣告變數的區別變數
- var、let、const宣告變數的區別變數
- js中var和let的快速區別JS
- 前端 let、const和var你真的瞭解麼?前端
- ES6中var,let,const的區別
- es6 let const與var 的區別
- 深入理解JS:var、let、const的異同JS
- 5分鐘掌握var,let和const異同
- var、let和const三者有哪些區別?
- 【前端面試】(四)JavaScript var let const的區別前端面試JavaScript
- var、let、const、解構、展開、new、this、class、函式函式
- 前端學習筆記 - var、let和const的用法前端筆記
- [譯] 在JavaScript中何時使用var、let及constJavaScript
- ES6中的let與var的區別
- var、let、const變數宣告的區別及特點變數