1. 程式人生 > 實用技巧 >js控制GIF圖片播放暫停

js控制GIF圖片播放暫停

有 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 關鍵字使用原則

  1. 不使用 var
  2. const 優先, let 次之

使用 const 宣告可以讓瀏覽器執行時強制保持變數不變,也可以讓靜態程式碼分析工具提前發現不合法的賦值操作。因此,很多開發者認為應該優先使用 const 來宣告變數,只在提前知道未來會有修改時,再使用 let。

本文是JavaScript高階程式設計(第四版)學習筆記