jQ 源碼解析(一)入口檢測
源碼解析
我看的源碼是 3.2.1 版的 JQ 文件
截取 JQ 文件主體如下:
(function( global, factory ) {
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 );
}
} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
//幾千行的功能代碼
......
......
})
再化簡一點:
(function(global, factory){
......
......
})(參數一,參數二)
可以看出這是一個自執行的匿名函數,傳入了兩個參數。
參數一(global):
typeof window !== "undefined" ? window : this
判斷當前函數執行環境是否支持 window 類型 ,不支持返回當前執行環境 this
參數二(factory):
一個函數,裏面是 JQ 的功能代碼,這裏先忽略
再分析匿名函數:
if ( typeof module === "object" && typeof module.exports === "object" )
這個判斷用於是否在 node 環境中,如果在 node 中則創建模塊把參數二的函數傳入等一列操作,不然則直接執行參數二的函數。
當然也會在參數二的函數中傳入當前執行環境(即參數一),參數二的函數就是 JQ 的主要內容。
所以,這個自執行匿名函數既防止了變量污染,還檢測了執行環境。
自執行函數
自執行函數,實質就是一個函數表達式,常用匿名函數做主體。
常見形式:
1. (function(val){ console.log(val) })('test')
2. (function(val){ console.log(val) }('test'))
因爲在 JavaScript 語言中,() 裏面不能包含語句(只能是表達式),所以解析器在解析到 function 關鍵字的時候,會把它們當作 function 表達式,而不是正常的函數聲明。
上面其實就是
var func = function(val){ console.log(val) };
func('test');
當然,JavaScript的 !取反操作、 && 與操作、|| 或操作、, 逗號等操作符也有上述效果
!function (val) { console.log(val) } ('test');
true && function (val) { console.log(val) } ('test');
false || function () { console.log("true ||") } ();
0, function () { console.log("0,") } ();
但是這樣會有缺點,雖然會自執行,但是是會有返回值的。
注意:因爲自執行函數是一個函數表達式,所以規範是在前後加上分號 ;,不然在存在其他表達式下會報錯。
(function(val){console.log(val)}('test'))console.log(123) //報錯
;(function(val){console.log(val)}('test'));console.log(123) //成功