jQuery的所有代碼放在了自調(diào)用的匿名函數(shù)中,防止命名污染
(function( window, undefined ) {
------
})( window );
我們?cè)谑褂?("div")獲取Dom元素,看起來就像是調(diào)了一個(gè)普通的函數(shù),每次調(diào)用jQuery就會(huì)實(shí)例化一個(gè)對(duì)象
一般訪問構(gòu)造函數(shù)中的方法是這樣操作,代碼如下:
function jQuery(selector) {
this.html= function () {
console.log("我是綠豆糕");
}
}
new jQuery("div").html();
上邊代碼每次訪問方法都要new一下,而我們看到的jQuery是這樣的方式調(diào)用的jQuery("div").html(),怎么才能達(dá)到這樣的效果呢? 想一想....
應(yīng)該是jQuery內(nèi)部幫我們實(shí)現(xiàn)了,調(diào)用jQuery函數(shù)的時(shí)候,返回值就應(yīng)該是一個(gè)實(shí)例對(duì)象
function jQuery(selector) {
this.html= function () {
console.log("我是綠豆糕");
}
return new jQuery(selector);
}
jQuery("div").html();
這樣做思路沒有問題,讓我們愉快的運(yùn)行一下
Paste_Image.png
糟糕.....整成堆棧溢出了,原因是new jQuery(),出現(xiàn)自己調(diào)用自己,發(fā)生遞歸卻沒有結(jié)束條件,這可咋整
其實(shí)這個(gè)問題jQuery內(nèi)部的實(shí)現(xiàn)方式卻相當(dāng)高明
//閉包環(huán)境,防止與外部命名污染
(function (window, undefined) {
var jQuery = function (selector) {
//返回init構(gòu)造函數(shù)的實(shí)例
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();
//導(dǎo)出接口,外部就可以訪問了,這也是為什么我們用$("div")也能得到Dom元素
window.jQuery = window.$ = jQuery;
})(window)
調(diào)用jQuery函數(shù)返回的是return new jQuery.prototype.init(selector),但是為什么html方法不在init構(gòu)造函數(shù)內(nèi)部也能調(diào)用成功,打印出"我是綠豆糕"呢?
原因是執(zhí)行了這行代碼
jQuery.prototype.init.prototype = jQuery.prototype;
init里面的this戈鲁,受制于作用域的限制辅柴,訪問不到j(luò)Query.prototype其它的屬性
jQuery內(nèi)部的一句'jQuery.fn.init.prototype=jQuery.fn'
將init的原型指向了jQuery的原型,這樣一來,jQuery產(chǎn)生的實(shí)例對(duì)象就能夠訪問jQuery原型上的屬性了
jQuery的原型中有html方法,這樣init的實(shí)例也能訪問了,因?yàn)樵屠^承
源碼中jQuery.fn是啥? 實(shí)際上就是jQuery.prototype
jQuery.fn = jQuery.prototype = {
......
}
jQuery.fn.init.prototype = jQuery.fn;
等效于我們剛才分析的這句
jQuery.prototype.init.prototype = jQuery.prototype;