任何庫與框架設(shè)計的第一個要點就是解決命名空間與變量污染的問題。jQuery就是利用了JavaScript函數(shù)作用域的特性,采用立即調(diào)用表達式包裹了自身的方法來解決這個問題。
jQuery的立即調(diào)用函數(shù)表達式的寫法有三種:
寫法1:
(function(window, factory) { factory(window) }(this, function() { return function() { //jQuery的調(diào)用 } }))
可以看出上面的代碼中嵌套了2個函數(shù),而且把一個函數(shù)作為參數(shù)傳遞到另一個函數(shù)中并且執(zhí)行,這種方法有點復(fù)雜,我們簡化一下寫法:
寫法2:
var factory = function(){ return function(){ //執(zhí)行方法 } } var jQuery = factory();
上面的代碼效果和方法1是等同的,但是這個factory有點變成了簡單的工廠方法模式,需要自己調(diào)用,不像是一個單例的jQuery類,所以我們需要改成“自執(zhí)行”,而不是另外調(diào)用。
寫法3:
(function(window, undefined) { var jQuery = function() {} // ... window.jQuery = window.$ = jQuery; })(window);
從上面的代碼可看出,自動初始化這個函數(shù),讓其只構(gòu)建一次。詳細說一下這種寫法的優(yōu)勢:
1、window和undefined都是為了減少變量查找所經(jīng)過的scope作用域。當(dāng)window通過傳遞給閉包內(nèi)部之后,在閉包內(nèi)部使用它的時候,可以把它當(dāng)成一個局部變量,顯然比原先在window scope下查找的時候要快一些。
2、undefined也是同樣的道理,其實這個undefined并不是JavaScript數(shù)據(jù)類型的undefined,而是一個普普通通的變量名。只是因為沒給它傳遞值,它的值就是undefined,undefined并不是JavaScript的保留字。
有童鞋留言到,為什么要傳遞undefined?
Javascript 中的 undefined 并不是作為關(guān)鍵字,因此可以允許用戶對其賦值。
我們看一個
var undefined = '慕課網(wǎng)' ;(function(window) { alert(undefined);//IE8 '慕課網(wǎng)' })(window)
IE8存在這個問題,當(dāng)然,大部分瀏覽器都是不能被修改的
如果函數(shù)調(diào)用不傳遞,參數(shù)默認就是undefined
;(function(window,undefined) { //undefined })(window)
jQuery為什么要創(chuàng)建這樣的一個外層包裹,其原理又是如何?
這里要區(qū)分2個概念一個是匿名函數(shù),一個是自執(zhí)行。顧名思義,匿名函數(shù),就是沒有函數(shù)名的函數(shù),也就是不存在外部引用。但是是否像下面代碼實現(xiàn)呢:
function(){ //代碼邏輯 }
上面這種寫法是錯了,聲明了它但是又不給名字又沒有使用,所以在語法上錯誤的,那么怎么去執(zhí)行一個匿名的函數(shù)呢?
要調(diào)用一個函數(shù),我們必須要有方法定位它、引用它。所以,我們要取一個名字:
var jQuery = function(){ //代碼邏輯 }
jQuery使用()將匿名函數(shù)括起來,然后后面再加一對小括號(包含參數(shù)列表),那么這小括號能把我們的表達式組合分塊,并且每一塊(也就是每一對小括號),都有一個返回值。這個返回值實際上也就是小括號中表達式的返回值。所以,當(dāng)我們用一對小括號把匿名函數(shù)括起來的時候,實際上小括號返回的,就是一個匿名函數(shù)的Function對象。因此,小括號對加上匿名函數(shù)就如同有名字的函數(shù)般被我們?nèi)〉盟囊梦恢昧?。所以如果在這個引用變量后面再加上參數(shù)列表,就會實現(xiàn)普通函數(shù)的調(diào)用形式。
最后,我們回到寫法1看看jQuery利用寫法3的寫法,然后把整個函數(shù)作為參數(shù)傳遞給另外一個函數(shù),主要是為了判斷jQuery在不同平臺的下的加載邏輯,主流的庫一般都有對 AMD 和 CommonJS 的支持代碼,看看jQuery的代碼:
if (typeof module === "object" && typeof module.exports === "object") { module.exports = global.document ? factory(global, true) : function(w) { if (!w.document) { throw new Error("jQuery requires a window with a document"); } return factory(w); }; } else { factory(global); }
總結(jié):全局變量是魔鬼, 匿名函數(shù)可以有效的保證在頁面上寫入JavaScript,而不會造成全局變量的污染,通過小括號,讓其加載的時候立即初始化,這樣就形成了一個單例模式的效果從而只會執(zhí)行一次。
請驗證,完成請求
由于請求次數(shù)過多,請先驗證,完成再次請求
打開微信掃碼自動綁定
綁定后可得到
使用 Ctrl+D 可將課程添加到書簽
舉報