項目中有一個邏輯是這樣的: 對當前元素的外層<li>元素進行操做, 個人作法是這樣的:$(someElement.parents('li')).xxxjavascript
因爲當前元素外層只有一個li元素,當時就沒有多想,後來仔細查看parents(selector)方法的說明,發現調用這個方法以後會返回全部匹配selector的元素;html
按理說,返回值應該是一個數組或者相似數組的結構猜對,而在這種結構上調用單個元素的方法(好比attr('id'))感受上應該報錯纔對;java
而後作了以下實驗:jquery
<!DOCTYPE html> <html> <head> <style> b, span, p, html body { padding: .5em; border: 1px solid; } b { color:blue; } strong { color:red; } </style> <script type="text/javascript" src="/jquery/jquery.js"></script> </head> <body> <div id="div1"> <p> <div id='div2'> <span> <b>個人父元素是:</b> </span> </div> </p> </div> <script> var parentEls = $("b").parents('div'); var names = ''; names = $(parentEls).attr('id'); $("b").append("<strong>" + names+ "</strong>"); console.info($(parentEls)); </script> </body> </html>
發如今element.parents(selector)的返回值上調用attr('id')時,jquery默認是在第0個祖先上調用此方法,,即全部祖先中最接近element的那個祖先,以下圖:數組
一開始查看parents(selector)的實現源碼,沒怎麼看懂,今天看了一下attr(xxx)的源碼,app
jQuery.fn.extend({ attr: function( name, value ) { return access( this, jQuery.attr, name, value, arguments.length > 1 ); }, removeAttr: function( name ) { return this.each(function() { jQuery.removeAttr( this, name ); }); } });
而後找到了access.js:this
// Multifunctional method to get and set values of a collection // The value/s can optionally be executed if it's a function var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) { var i = 0, len = elems.length, bulk = key == null; // Sets many values if ( jQuery.type( key ) === "object" ) { chainable = true; for ( i in key ) { access( elems, fn, i, key[i], true, emptyGet, raw ); } // Sets one value } else if ( value !== undefined ) { chainable = true; if ( !jQuery.isFunction( value ) ) { raw = true; } if ( bulk ) { // Bulk operations run against the entire set if ( raw ) { fn.call( elems, value ); fn = null; // ...except when executing function values } else { bulk = fn; fn = function( elem, key, value ) { return bulk.call( jQuery( elem ), value ); }; } } if ( fn ) { for ( ; i < len; i++ ) { fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) ); } } } return chainable ? elems : // Gets bulk ? fn.call( elems ) : //好像緣由就在這裏:elems[0] len ? fn( elems[0], key ) : emptyGet; };
大概就是在第0個元素上調用的方法,因此我在代碼中那麼寫就歪打正着了,若是元素外層有不止一個匹配selector的祖先,而我要在第二個祖先上調用方法,這麼寫就會出錯了;
spa