JavaScript Weird Part (37)- IIFEs 與安全程式碼

IIFEs 大量使用在資源庫及框架中,用處非常廣泛,以下是一個 IIFE 的例子:

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

回到執行堆思考底層的運作方式,程式第一次載入,會建立全域執行環境,但是裡面沒有東西,因為上面的例子沒有變數也沒有函數陳述句被提昇。但是當解析器執行到整個 IIFE

當它到了函數表示式部分,它會創函數物件記憶體,這是匿名的。然後它看到這些呼叫函數的括號的時候,一個新的執行環境建立,給這個剛剛創造的匿名函數,並且逐行執行函數內的程式

這一行程式碼會在執行階段進到執行環境的變數環境中,而不是在全域環境。因為它在函數自己的執行環境裡面。所以任何宣告的變數,都在函數內部創造,不會接觸到全域環境

1
var greeting = "Hello";

這是一個對撰寫程式碼很有用的做法,例如現在引入 2 個 JavaScript 檔案,像這樣:

1
2
3
4
<body>
<script src="./greet.js"></script>
<script src="./app.js"></script>
</body>
1
2
// greeting.js 的程式碼內容
var greeting = "Hola";
1
2
3
4
5
6
// app.js 的程式碼內容
(function(name) {
var greeting = "Hello";
console.log(greeting + "" + name);
})("John");
console.log("greeting"); //Hola

以前這會產生衝突,但使用 IIFE 之後卻不會,為什麼?因為當執行 greeting.js 的內容的時候,全域執行環境在這行後面被執行,記憶體裡有變數greeting及其值Hola

然後解析器看到整個 IIFE,藉由呼叫函數表示式,而建立新的執行環境。到了函數內變數 greeting的變數環境的時候,這兩個變數 greeting 都存在,但是位於不同的執行環境內、不同的記憶體位址。所以我們可以把程式碼包在 IIFE 裡面,保證它不會和其他匯入應用程式的程式碼產生衝突。

所以打開一些資源庫或套件、函數的時候,如果打開原始碼,在最底部看到的東西就是括號及函數,因為所有程式碼都被包裹在 IIFE 裡面。

了解這些模式,就有助於我們在創造一些可重複利用的東西時,可以確保程式碼不會產生衝突,或者不小心把程式碼放入全域物件。

Powered by Hexo and Hexo-theme-hiker

Copyright © 2013 - 2019 CYC'S BLOG All Rights Reserved.

UV : | PV :