[JS奇怪的世界]No.37 框架小叮嚀-IIFEs與安全程式碼

前言

前面我們已經講過 IIFE ,而許多知名框架都會使用到這個技術,所以這章節就要來講講 IIFE 和安全程式碼以及為何它很有用。

IIFE

這裡有一個課程提供的範例。

1
2
3
4
5
// IIFE
(function(name) {
var greeting = 'Hello';
console.log(greeting + ' ' + name);
})('Joun');

首先讓我們從執行堆來瞭解它做了什麼。

上面是我們正在執行中的 IIFE,而因為我們使用了括號執行了它,創造了一個執行環境。

執行環境

而這個做法會讓在這裡面的變數,都只會存在於函數內部中,而不是全域環境,所以我們可以試著這樣玩

通常我們要輸出 1…10,都會這樣寫 ↓

1
2
3
for(var i = 0 ; i < 10; i++) {
console.log(i + 1);
}

輸出完畢後我們再看一次目前的 i 會是怎樣 ↓

1
2
3
4
for(var i = 0 ; i < 10; i++) {
console.log(i + 1);
}
console.log(i);

i

可以看到 i 變成 10 了,如果我們預期是這樣子,那就沒有錯,但如果不是呢?我只希望 i 存在於這個迴圈中,那就有問題了,此時就可以使用 IIEF 來解決 ↓

1
2
3
4
5
6
7
(function () {
for(var i = 0; i < 10; i++) {
console.log( i + 1);
}
})()

console.log(i);

IIEF

所以上面這例子也可以證明,這些變數只會存活於 IIFE 中。

那如果是這樣子的狀況呢?

1
2
3
4
5
6
7
var myname = 'Ray';

(function () {
for(var i = 0; i < 10; i++) {
console.log(i + 1 + myname);
}
})();

範圍鏈

可以發現範圍鏈也是可以正常運作的,當然也可以這樣寫 ↓

1
2
3
4
5
6
7
8
var myname = 'Ray';

(function () {
for(var i = 0; i < 10; i++) {
var myname = 'Tomy';
console.log(i + 1 + myname);
}
})();

myname

你可能會說 myname 已經變成 Tomy 了阿! 那我們再加入一行看看目前的 myname

1
2
3
4
5
6
7
8
9
var myname = 'Ray';

(function () {
for(var i = 0; i < 10; i++) {
var myname = 'Tomy';
console.log(i + 1 + myname);
}
})();
console.log(myname);

myname

所以我們可以將程式碼包在 IIFE 中確保它不會和其他東西有衝突甚至污染,你可能會說根本不清楚,那我們這樣寫就會更清楚,知道這種做法是會汙染全域變數 ↓

1
2
3
4
5
6
var myname = 'Ray';
for(var i = 0 ; i < 10; i++) {
var myname = 'Tomy';
console.log(i + 1 + myname);
}
console.log(myname);

汙染全域變數

課程上也有故意影響全域物件的寫法。

1
2
3
4
5
6
7
8
9
10
var myname = 'Ray';

(function (global) {
for(var i = 0; i < 10; i++) {
var myname = 'Tomy';
global.myname = myname
console.log(i + 1 + myname);
}
})(window);
console.log(myname);

myname

那這個做法其實就是利用傳參考特性來影響全域物件的寫法。

圖源

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

0%