源碼學習第七天(水滴石穿)
// Take an array of elements and push it onto the stack // (returning the new matched element set) pushStack: function(elems) { //elem可以是數組和偽數組 // Build a new jQuery matched element set var ret = jQuery.merge(this.constructor(), elems); // Add the old object onto the stack (as a reference)ret.prevObject = this; ret.context = this.context; // Return the newly-formed element set return ret; //jQuery節點對象 },
jQuery節點對象入棧,這個方法給用戶使用的人不多,但是在另外的方法封裝需要用到棧的知識,所以需要了解一下。
據上圖結合代碼所知,$(‘div‘).pushStack($(‘span‘))就是把span添加到棧中,這時候返回的是$(‘span‘)。
具體來說說代碼的寫法,var ret = jQuery.merge(this.constructor(), elems);這一句體現了花式秀js,其實this.constructor()就是jQuery()的意思,首先this指向了jQuery的實例,this.constructor就是原型的constructor屬性指向jQuery。這句話的意思就是把添加的jQuery節點對象與一個空jQuery節點對象合並,返回一個新的jQuery節點對象,再給這個對象添加context屬性,prevObject屬性存上一個jQuery節點 res.prevObject = this;這個this指向init,返回新的jQuery節點res
最重要的一點是每次調用$(‘ ‘).pushStack(elem)都是重新開辟一個棧,把elem添加到$(‘ ‘)上,然後返回一個整體的res對象,順帶一說,如果$(‘ ‘)有多個節點,多個(jQ)節點屬於同一層,而不是一個( jQ )節點一層。[ 每個棧底層都有一個$(document),再下一層就沒了,返回的res就是init{} ]
each: function(callback, args) { return jQuery.each(this, callback, args); }, ready: function(fn) {// Add the callback jQuery.ready.promise().done(fn); return this; }, slice: function() { return this.pushStack(core_slice.apply(this, arguments)); }, first: function() { return this.eq(0); }, last: function() { return this.eq(-1); }, eq: function(i) { var len = this.length, j = +i + (i < 0 ? len : 0); return this.pushStack(j >= 0 && j < len ? [this[j]] : []); }, map: function(callback) { return this.pushStack( jQuery.map(this, function(elem, i) { return callback.call(elem, i, elem); }) ); }, end: function() { return this.prevObject || this.constructor(null); }, // For internal use only. // Behaves like an Array‘s method, not like a jQuery method. push: core_push, sort: [].sort, splice: [].splice
接下來就是各種常用方法each、ready、slice、first、last、eq、map、end,各個方法間有依賴關系。
each循環:這個each循環是$(‘ ‘).each() 是根據$.each()進一步的封裝。
ready:入口函數,也是調用內部封裝的函數,要以後了解到調用函數的意義才行
slice:截取,通過棧方法的和借用數組的方法 ‘this.pushStack(core_slice.apply(this, arguments));‘ 借用中的this指向調用的this,也就是init;core_slice也就是[].slice,arguments參數集合,call並不能用參數集合,只能一個一個寫出來。
eq: j = +i + (i < 0 ? len : 0); 一句話就解決了負數和正數的i的取值,正數的時候+i + 0,負數的時候+i+jQuery節點對象長度(+表示轉數字類型); ‘return this.pushStack(j >= 0 && j < len ? [this[j]] : []);‘ 如果j也就是處理後的數字在[0,len)之間就把[ this[j] ]添加到棧,否則就將[ ]添加到棧 (this[j]就是原生DOM節點 ),通過返回的res得到想要的jQuery節點對象。
first、last都是在eq的基礎上操作 first:qe(0) last:eq(-1)
map:映射,調用了jQuery.map( )
end:往棧裏面走一層 ‘return this.prevObject || this.constructor(null);‘ 如果prevObject存在也就是下一層有值,就返回,沒有就返回$(null) => init { }
源碼學習第七天(水滴石穿)