(譯)(function (window, document, undefined) {})(window, document); 真正的意思


由於非常感興趣, 我查詢了很多關於IIFE (immediately-invoked function expression)的東西, 如下:

(function (window, document, undefined) {// })(window, document);

那么為什么不寫一篇關於它的文章呢? ;-)

首先,它有一系列不同的東西。從頭開始:

作用域

JavaScript有function 作用域, 所以它被用在必須私有作用域的地方。舉個例子:

(function (window, document, undefined) {var name = 'Todd';})(window, document);console.log(name); // name沒有定義, 它在一個不同的作用域里面

Simple.

它的工作原理

一個普通的函數是這樣的:

var logMyName = function (name) {console.log(name);};logMyName('Todd');

我們可以調用它的范圍和我們提供的作用域沒有關系。“IIFE”被創造的原因是它們是立即執行表達式,這意味着他們一創建就馬上被執行,當然我們不能再次執行它們。 如下:

var logMyName = (function (name) {console.log(name); // Todd})('Todd');

這里的秘密武器是這個, (還記得上面分配了一個變量的例子嗎?):

(function () {})();

如果沒有額外的小括號,他們就不能工作:

function () {}();

雖然有一些技巧可以強制讓javascript讓它工作,如下使用! 字符:

!function () {}();

當然還有下面的變體:

+function () {}();-function () {}();~function () {}();

但是我不會使用他們.

查看 Disassembling JavaScript’s IIFE Syntax 這是一篇詳細介紹IIFE語法和它的變體的文章。

參數

現在我們知道它是怎么工作了,我們可以往IIFE中傳參:

(function (window) {})(window);

這個的工作原理是什么? 注意, 最后的 (window); 是函數的調用, 並且我們傳入了一個window 對象。它通過這個傳入到函數的變量,這個變量我們也命名為window 。 你可以認為這個是沒有意義的,但是現在我們使用window 更好. 那么我們還能做什么? 我們可以傳入更多的東西, 讓我們傳入一個document 對象:

(function (window, document) {// we refer to window and document normally})(window, document);

局部變量的調用比全局變量更快, 當然這是在超大規模的情況下,一般情況我們不會感覺到速度的影響 - 但是如果我們用全局變量很多也是值得考慮的。

什么是 undefined?

在ECMAScript 3, undefined是變量. 意味着它的值可以被定義,比如 undefined = true; 在 ECMAScript 5使用嚴格遵守模式('use strict';) 這個賦值會報錯.:

(function (window, document, undefined) {})(window, document);

下面是可以得:

undefined = true;(function (window, document, undefined) {// undefined is a local undefined variable})(window, document);

壓縮

壓縮我們的變量是IIFE模式真正實用的地方。局部變量的名字可以在它們傳入函數中進行改變,所以我們如下調用:

(function (window, document, undefined) {console.log(window); // Object window})(window, document);

變為:

(function (a, b, c) {console.log(a); // Object window})(window, document);

想象下,所有的你引入的類庫里面的window 和 document 很好的壓縮。 如下面的jquery類庫的調用:

(function ($, window, document, undefined) {// use $ to refer to jQuery// $(document).addClass('test');})(jQuery, window, document);
(function (a, b, c, d) {// becomes// a(c).addClass('test');})(jQuery, window, document);

這意味着你不用使用 jQuery.noConflict(); 任何 $ 都會執行jquery. 學習這個對於變量的作用域會對你幫助很大。一個好的壓縮工具會把undefined壓縮為c。undefined 的命名是無關緊要的,我們只是需要用它來判斷一個對象是否有值或者有沒有定值而已

非瀏覽器全局環境

比如Node.js, 瀏覽器不在是全局對象,我們會使用IIFE讓他在跨環境運行:

(function (root) {})(this);

在瀏覽器中,this 指向 window 對象, 所以我們不需要傳入 window, 我們可以使用this來縮短. 我喜歡使用root來命名它,如果在非瀏覽器環境也合適

。 如果你對普通的解決方案感興趣 這里是一個UMD包裝:

(function (root, factory) {if (typeof define === 'function' && define.amd) {define(factory);} else if (typeof exports === 'object') {module.exports = factory;} else {root.MYMODULE = factory();}})(this, function () {// });

在瀏覽器, root.MYMODULE = factory(); 是我們的IIFE模塊, 其他情況(如 Node.js) 它會調用 module.exports 或者當 typeof define === 'function' && define.amd為true 則調用requireJS。當然這個另外一個故事了, 我強烈推薦你看這篇文章 UMD repo.







免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM