目錄node
轉載請註明出處數組
@瀏覽器
1..attr()的四種用法
大體用法:函數
用法詳解:
(1)..attr()源代碼定義:this
jQuery.fn.extend( { attr: function( name, value ) { return access( this, jQuery.attr, name, value, arguments.length > 1 ); } }
可見,.attr的核心是函數access(),而該函數不須要實例便可調用,屬於直接定義在jQuery上的'靜態函數'.code
jQuery.access()源代碼定義:對象
var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { var i = 0, length = elems.length, bulk = key == null; //bulk用於判斷key值是否爲null(注:null==undefined的結果爲true) // 設置多個值(當key參數爲對象時,注:jQuery.type實現原理是[[class]]) if ( jQuery.type( key ) === "object" ) { chainable = true; for ( i in key ) { access( elems, fn, i, key[ i ], true, emptyGet, raw ); } // 設置一個值(當key爲非對象類型時) } else if ( value !== undefined ) { chainable = true; if ( !jQuery.isFunction( value ) ) { raw = true; //判斷value值是否爲函數類型.若是不是函數,設置raw值,爲if(fn)以及if(bulk)埋下伏筆 } if ( bulk ) { //批處理 // 批處理是執行在整個屬性集上的 if ( raw ) { fn.call( elems, value ); fn = null; // 當value爲函數時又有點不一樣 } else { bulk = fn; fn = function( elem, key, value ) { return bulk.call( jQuery( elem ), value ); }; } } if ( fn ) { //對elems中的每個元素應用fn方法,第三個參數由raw決定 for ( ; i < length; i++ ) { fn( elems[ i ], key, raw ? value : value.call( elems[ i ], i, fn( elems[ i ], key ) ) ); } } } return chainable ? //返回值設定 elems : // Gets bulk ? fn.call( elems ) : length ? fn( elems[ 0 ], key ) : emptyGet; }
如上圖,因爲access函數用途並不侷限於咱們的.attr(),做爲像筆者同樣的jQuery初學者,源代碼中有許多代碼語句咱們不能很好的理解(好比:if(bulk)部分).因爲暫時接觸到的jQuery內容較少較淺,咱們若是一味深究,可能既搞不清楚原理,還浪費時間.因此,咱們能夠用一種簡化的思想來分析問題: 只關注代碼中跟咱們當前問題有關的部分,忽略無關的,用不到的部分.遞歸
具體作法:咱們將.attr()的四種用法的實際傳參狀況帶入jQuery.access函數的定義中,刪除咱們進不去的if語句代碼塊,只保留會用到的代碼語句.索引
attr定義:接口
attr: function( name, value=undefined ) { return jQuery.access( this, jQuery.attr, name, value=undefined, arguments.length > 1 ); }
access調用簡化:
var access = function( this, jQuery.attr, name, value=undefined, chainable=false, emptyGet=undefined, raw=undefined ) { var i = 0, length = this.length, //jQuery對象的length屬性(jQuery對象老是有length屬性,它是類數組對象) bulk = false; return jQuery.attr( this[0], name ); };
一樣,咱們找到jQuery.attr()靜態方法的源代碼定義,用一樣的簡化方法分析,獲得:
jQuery.attr()完整源碼:
attr: function( elem, name, value ) { // elem:DOM對象 name:屬性名/鍵名 value:屬性值 var ret, hooks, nType = elem.nodeType; // 節點類型 // 屏蔽屬性節點,文本節點與註釋節點 if ( nType === 3 || nType === 8 || nType === 2 ) { return; } // 當屬性不支持getAttribute方法時,回調jQuery.prop()方法--從操做attribute變成了操做property if ( typeof elem.getAttribute === "undefined" ) { return jQuery.prop( elem, name, value ); } //下面的都是DOM元素elem支持getAttribute的狀況 // 全部標籤特性(attributes)都是小寫(處理兼容:有的瀏覽器對同一屬性的名稱可能大小寫不停) // 若是某一個是已定義的,抓取必要的鉤子 if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { // 非元素節點或者是XML文本中的元素 name = name.toLowerCase(); hooks = jQuery.attrHooks[ name ] || ( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook ); } if ( value !== undefined ) {//若是value在傳參時未被忽略 if ( value === null ) { jQuery.removeAttr( elem, name );//傳入第三個參數爲null時,調用jQuery.removeAttr移除對應屬性 return; } if ( hooks && "set" in hooks && ( ret = hooks.set( elem, value, name ) ) !== undefined ) { return ret; } elem.setAttribute( name, value + "" ); return value; } if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { return ret; } ret = jQuery.find.attr( elem, name ); // 不存在的屬性會返回null,咱們將之統一爲undefined return ret == null ? undefined : ret; }
jQuery.attr()簡化:
attr: function( elem, name, value=undefined ) { // elem:DOM對象 name:屬性名/鍵名 value:屬性值 var ret, hooks, nType = 1; ret = jQuery.find.attr( elem, name ); return ret; }
其中,惟一不肯定的是jQuery.find.attr,然而咱們繼續找下去則是有關Sizzle選擇器引擎的問題,這對於咱們初學者來講過於複雜.所以,咱們再簡化一下,帶入實際情景,檢測這一函數的輸出:
var $p = $('#jQueryTest')[0]; console.log(jQuery.find.attr($p,'id')); //jQueryTest
所以,大概知道該函數該種傳參狀況下的做用是返回指定DOM元素的指定屬性的值.
1.由jQuery.access簡化代碼中的return jQuery.attr( this[0], name );
可知,只傳入一個name參數的狀況下,確實只會返回jQuery對象中的索引爲'0'的DOM對象的指定屬性的屬性值.
2.由jQuery.att()完整代碼中
if ( typeof elem.getAttribute === "undefined" ) {
return jQuery.prop( elem, name, value );
}
可知:若是不支持get/setAttibute,那麼原來的針對特性(attibute)的操做就會變成DOM元素屬性(property)的操做.
attr定義:
attr: function( name, value) { //此時的this是一個類數組 return jQuery.access( this, fn=jQuery.attr, name, value, chainable=true); }
access調用簡化:
var access = function( this, jQuery.attr, name, value, chainable=true, emptyGet=undefined, raw=undefined ) { var i = 0, length = this.length, //jQuery對象的length屬性,表示找到的匹配的DOM元素的個數 bulk = false; chainable = true; if ( !jQuery.isFunction( value ) ) { //當value值不爲函數時,設置raw爲true,這是爲了下一步if(jQuery.attr)中的raw判斷作鋪墊 raw = true; } if ( jQuery.attr ) { //jQuery.attr,爲true for ( ; i < length; i++ ) { //用for循環是由於此時的this是一個包含多個DOM元素的jQuery對象 jQuery.attr( this[ i ], name, raw ? value : value.call( elems[ i ], i, jQuery.attr( this[ i ], name ) ) );//raw爲true,也就是value不爲函數時,用value做第三參數 } } } return this; //返回jQuery對象自己 };
而,咱們用簡化的方法分析此種狀況下的jQuery.attr(this,name,value):
attr: function( this[i], name, value ) { var ret, hooks, nType = this[i].nodeType; if ( value !== undefined ) { //判斷爲true,進入if語句 if ( value === null ) { jQuery.removeAttr( this[i], name );//若是value爲null,刪除該jQuery對象的全部匹配元素的指定屬性 return; } this[i].setAttribute( name, value + "" );//設置當前DOM元素的指定屬性的屬性值 return value; } ret = jQuery.find.attr( this[i], name ); //刪除了屬性,返回null;不然,返回指定屬性的屬性值 return ret == null ? undefined : ret; //若是刪除了指定屬性,返回undefined;若是修改了屬性,返回指定屬性值 }
attr定義:
attr: function( name=attrObject ) { return jQuery.access( this, jQuery.attr, name=attrObject, value=undefined, false); }
access調用簡化:
var access = function( this, fn, name, value=undefined, chainable=false, emptyGet=undefined, raw=undefined ) { var i = 0, length = this.length, //元素的length屬性 bulk = false; // 設置多個value值 if ( jQuery.type( name ) === "object" ) { //若是傳入的name形參爲對象類型 chainable = true; for ( i in name ) { //對每個對象中的屬性名及屬性值再次調用自己(遞歸) access( this, fn, i, name[ i ], true, emptyGet, raw ); } } return elems; //返回jQuery對象自己 };
可見,對於一個由"屬性-屬性值"鍵值對構成的對象,會對其中的每個屬性都調用access設置一次.因爲代碼中使用的for-in循環,因此enumerable爲false的鍵值對是無效的.
attr定義:
attr: function( name, value=attrFn ) { return jQuery.access( this, jQuery.attr, name, value=attrFn, chainable=true ); }
access調用簡化:
var access = function( this, jQuery.attr, name, value=attrFn, chainable=true, emptyGet=undefined, raw=undefined ) { var i = 0, length = this.length, //jQuery對象的length屬性 bulk = false; chainable = true; if ( jQuery.attr ) { //true,進入if語句 for ( ; i < length; i++ ) { jQuery.attr( this[ i ], name, attrFn.call( this[ i ], i, jQuery.attr( this[ i ], name ) ) // 調用attrFn,其返回值做爲第三個參數 ); } } return elems; // 返回jQuery對象自己 };
由attrFn.call( this[ i ], i, jQuery.attr( this[ i ], name ) )
可知,attrFn的參數限制就是源自這一行代碼:(this[i]是調用attrFn的元素,後面兩個是參數,一個是jQuery對象中的索引值,一個是當前元素的指定屬性name的值的查詢返回)
[特別注意:attrFn的兩個參數雖然有規定,可是不須要咱們真的傳參,而是函數體內部使用索引值或者當前屬性值的一個接口]