jQuery的所有代碼放在了自調用的匿名函數中,防止命名污染
(function( window, undefined ) {
------
})( window );
我們在使用$("div")獲取Dom元素,看起來就像是調了一個普通的函數,每次調用jQuery就會實例化一個對象
一般訪問構造函數中的方法是這樣操作,代碼如下:
function jQuery(selector) {
this.html= function () {
console.log("我是綠豆糕");
}
}
new jQuery("div").html();
上邊代碼每次訪問方法都要new一下,而我們看到的jQuery是這樣的方式調用的jQuery("div").html(),怎么才能達到這樣的效果呢? 想一想....
應該是jQuery內部幫我們實現了,調用jQuery函數的時候,返回值就應該是一個實例對象
function jQuery(selector) {
this.html= function () {
console.log("我是綠豆糕");
}
return new jQuery(selector);
}
jQuery("div").html();
這樣做思路沒有問題,讓我們愉快的運行一下
Paste_Image.png
糟糕.....整成堆棧溢出了,原因是new jQuery(),出現自己調用自己,發生遞歸卻沒有結束條件,這可咋整
其實這個問題jQuery內部的實現方式卻相當高明
//閉包環境,防止與外部命名污染
(function (window, undefined) {
var jQuery = function (selector) {
//返回init構造函數的實例
return new jQuery.prototype.init(selector);
}
jQuery.prototype = {
constructor: jQuery,
init: function (selector) {
},
html: function () {
console.log("我是綠豆糕");
}
}
//init的原型指向jQuery的原型,這樣我們就能訪問jQuery原型中的方法了
jQuery.prototype.init.prototype = jQuery.prototype;
jQuery("div").html();
//導出接口,外部就可以訪問了,這也是為什么我們用$("div")也能得到Dom元素
window.jQuery = window.$ = jQuery;
})(window)
調用jQuery函數返回的是return new jQuery.prototype.init(selector),但是為什么html方法不在init構造函數內部也能調用成功,打印出"我是綠豆糕"呢?
原因是執行了這行代碼
jQuery.prototype.init.prototype = jQuery.prototype;
init里面的this,受制于作用域的限制,訪問不到jQuery.prototype其它的屬性
jQuery內部的一句'jQuery.fn.init.prototype=jQuery.fn'
將init的原型指向了jQuery的原型,這樣一來,jQuery產生的實例對象就能夠訪問jQuery原型上的屬性了
jQuery的原型中有html方法,這樣init的實例也能訪問了,因為原型繼承
源碼中jQuery.fn是啥? 實際上就是jQuery.prototype
jQuery.fn = jQuery.prototype = {
......
}
jQuery.fn.init.prototype = jQuery.fn;
等效于我們剛才分析的這句
jQuery.prototype.init.prototype = jQuery.prototype;