js控制GIF圖片播放暫停
阿新 • • 發佈:2020-12-29
有 3 個關鍵字可以宣告變數: var 、 const 和 let。
變數可以用於儲存任何型別的資料。
1 var 關鍵字
var message; //不初始化的情況下,變數會儲存一個特殊值 undefined
var message = "hi"; // 宣告並且初始化變數
1.1 var 宣告作用域
使用 var 操作符定義的變數會成為包含它的函式的區域性變數
function test() {
var message = "hi"; // 區域性變數
}
test();
console.log(message); // 出錯!
在函式內定義變數時省略 var 操作符,可以建立一個全域性變數
function test() { message = "hi"; // 全域性變數 } test(); console.log(message); // "hi"
雖然可以通過省略 var 操作符定義全域性變數,但不推薦這麼做。在區域性作用域中定
義的全域性變數很難維護,在嚴格模式下,如果像這樣給未宣告的變數賦值,則會導致丟擲 ReferenceError 。
一次定義多個變數
var message = "hi",
found = false,
age = 29;
1.2 宣告提升(hoist)
function foo() {
console.log(age);
var age = 26;
}
foo(); // undefined
上一段不會報錯,是因為 ECMAScript 執行時把它看成等價於如下程式碼:
即,把所有變數宣告提升到作用域頂部
function foo() {
var age;
console.log(age);
age = 26;
}
foo(); // undefined
因此多次宣告同一個變數也沒有問題
function foo() {
var age = 16;
var age = 26;
var age = 36;
console.log(age);
}
foo(); // 36
2 let 關鍵字
2.1 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 沒有定義
2.2 let 不允許同一個塊作用域中出現冗餘宣告
var name;
var name; // 不會報錯
let age;
let age; // SyntaxError;識別符號 age 已經宣告過了
巢狀使用相同的識別符號不會報錯
let age = 30; // 作用域是整個塊
console.log(age); // 30
if (true) {
let age = 26; // 作用域是if塊
console.log(age); // 26
}
這兩個關鍵字宣告的並不是不同型別的變數,它們只是指出變數在相關作用域如何存在
var name;
let name; // SyntaxError
let age;
var age; // SyntaxError
2.3 let 不會提升(hoist)
console.log(age); // ReferenceError:age 沒有定義
let age = 26;
2.4 let 全域性作用域宣告不會成為 window 物件
var 宣告的變數會成為 window 物件的屬性
var name = 'Matt';
console.log(window.name); // 'Matt'
let age = 26;
console.log(window.age); // undefined
2.5 let 不能條件宣告
<script>
var name = 'Nicholas';
let age = 26;
</script>
<script>
// 假設指令碼不確定頁面中是否已經聲明瞭同名變數
// 那它可以假設還沒有宣告過
var name = 'Matt';
// 這裡沒問題,因為可以被作為一個提升宣告來處理
// 不需要檢查之前是否宣告過同名變數
let age = 36;
// 如果 age 之前宣告過,這裡會報錯
</script>
對於 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>
2.6 for 迴圈中的 let 宣告不會滲透到迴圈體外部
for (var i = 0; i < 5; ++i) {
// 迴圈邏輯
}
console.log(i); // 5
for (let i = 0; i < 5; ++i) {
// 迴圈邏輯
}
console.log(i); // ReferenceError: i 沒有定義
3 const 宣告
-
const 的行為與 let 基本相同,唯一一個重要的區別是用它宣告變數時必須同時初始化變數
-
嘗試修改 const 宣告的變數會導致執行時錯誤
const age = 26;
age = 36; // TypeError: 給常量賦值
- const 宣告的限制只適用於它指向的變數的引用。如果 const 變數引用的是一個物件,那麼修改這個物件內部的屬性並不違反 const 的限制
const person = {};
person.name = 'Matt'; // ok
- 不能用 const 來宣告迭代變數(因為迭代變數會自增)
for (const i = 0; i < 10; ++i) {} // TypeError:給常量賦值
- 如果你只想用 const 宣告一個不會被修改的 for 迴圈變數,那也是可以的。也就是說,每次迭代只是建立一個新變數
let i = 0;
for (const j = 7; i < 5; ++i) {
console.log(j);
}
// 7, 7, 7, 7, 7
for (const key in {a: 1, b: 2}) {
console.log(key);
}
// a, b
for (const value of [1,2,3,4,5]) {
console.log(value);
}
// 1, 2, 3, 4, 5
4 關鍵字使用原則
- 不使用 var
- const 優先, let 次之
使用 const 宣告可以讓瀏覽器執行時強制保持變數不變,也可以讓靜態程式碼分析工具提前發現不合法的賦值操作。因此,很多開發者認為應該優先使用 const 來宣告變數,只在提前知道未來會有修改時,再使用 let。
本文是JavaScript高階程式設計(第四版)學習筆記