[JS奇怪的世界]No.24 框架小叮嚀:偽裝命名空間

偽裝命名空間

偽裝命名空間

命名空間在現在的程式語言是變數與函數的容器,通常是用來維持變數和函數的名稱分開避免 A 感染到 B,但 JavaScript 其實並沒有命名空間這種東西,可是我們可以利用物件來偽裝命名空間

課程提供了一個範例 ↓

1
2
3
4
var greet = 'Hello!';
var greet = 'Hola!';

console.log(greet);

console.log 會輸出哪一個?

我們都知道所有 JavaScript 中的變數及函數都會歷經創造階段 (Hoisting),並且所有變數都會被賦予預設值 (undefined),當我們若將程式拆開來看就會比較清楚 ↓

1
2
3
4
5
var greet;

greet = 'Hello!';
greet = 'Hola!';
console.log(greet);

greet

一般來講我們可能會使用到相同的變數名稱,在其他程式語言中可以使用 命名空間 (namespace) 來解決相同變數或函數衝突問題,但在 JavaScript 並沒有 命名空間 (namespace) 這種東西,所以我們可以利用物件來製作偽裝命名空間,就像這樣 ↓

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var greet;

greet = 'Hello!';
greet = 'Hola!';
console.log(greet);

var english = {};
var spanish = {};

english.greet = 'Hello!';
spanish.greet = 'Hola!';

console.log(english);
console.log(spanish);

這樣子就可以持有兩個相同名稱的變數 (greet),而這也就是所謂的偽裝命名空間,這樣做的好處就是可以閃過變數衝突問題,所以其實是在利用物件的特性來製作的。

但是不能這樣子寫 ↓

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var greet;

greet = 'Hello!';
greet = 'Hola!';
console.log(greet);

var english = {};
var spanish = {};

english.greetings.greet = 'Hello!';
spanish.greet = 'Hola!';

console.log(english);
console.log(spanish);

致命錯誤

這樣是會出現一個致命錯誤的,why?首先在點運算子相同優先性的狀況下就會考慮相依性,這是我們理解的觀念,而點運算子的相依性是左相依性,所以會從左邊開始執行,所以 english 會在裡面尋找一個叫 greetings 的變數,但是因為 greetings 還沒有被建立,所以這會是空的,那該如何解決呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var greet;

greet = 'Hello!';
greet = 'Hola!';
console.log(greet);

var english = {
greetings: {},
};
var spanish = {};

english.greetings.greet = 'Hello!';
spanish.greet = 'Hola!';

console.log(english);
console.log(spanish);

greetings

這樣就可以解決問題了,回頭講講上面的原因,為什麼不能這樣寫 ↓

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var greet;

greet = 'Hello!';
greet = 'Hola!';
console.log(greet);

var english = {};
var spanish = {};

english.greetings.greet = 'Hello!';
spanish.greet = 'Hola!';

console.log(english);
console.log(spanish);

首先剛剛有講到點運算子是左相依性,所以 english.greetings 先被執行完畢了,但是 english 底下並沒有 greetings,所以 JavaScript 將它變成預設值 undefined,那程式碼就會變成這樣 ↓

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var greet;

greet = 'Hello!';
greet = 'Hola!';
console.log(greet);

var english = {};
var spanish = {};

undefined.greet = 'Hello!';
spanish.greet = 'Hola!';

console.log(english);
console.log(spanish);

undefined 本身就不是一個物件,所以就會跳錯哩~

圖源

JavaScript 全攻略:克服 JS 奇怪的部分

0%