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