DOM对象实例方法prop源码:
prop: function( name, value ) { return access( this, jQuery.prop, name, value, arguments.length > 1 ); }如果传入一个参数,那么这时候value是undefined,第五个参数是false,为了方便我们还是附上access源码:
如果是获取属性(value是false,chainable和bulk都是false):调用fn(elem[0],key)那么回调jQuery.prop方法,传入参数第一个DOM对象和key值,也就是只是获取第一个DOM对象的属性值!这和attr获取时候的结果是一样的!
如果是设置属性:传入access里面第三个和第四个参数都存在,同时第五个参数是true,这时候为每一个调用对象的DOM对象都调用jQuery.prop方法传入的参数是DOM元素,key和value。如prop("prop_a","codePlayer")
var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) { var i = 0, length = elems.length, bulk = key == null; // Sets many values if ( jQuery.type( key ) === "object" ) { chainable = true; for ( i in key ) { jQuery.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 < 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; };jQuery.prop方法源码: 你要弄明白如果不通过下标形式对DOM赋值获得property属性,那么document.getElementById("n2").data_key就是false,但是这都
算是attribute!但是property和attribute也有交叉的地方,如id,calss和className等(可以通过firebug看出)。
jQuery.extend({ propFix: { "for": "htmlFor", "class": "className" }, //prop里面调用prop(elem[0],"name") prop: function( elem, name, value ) { var ret, hooks, notxml, nType = elem.nodeType; // don't get/set properties on text, comment and attribute nodes if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { return; } //不是XML元素 notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); if ( notxml ) { // Fix name and attach hooks //获取hooks,如果这个hooks已经存在,也就是内置的几种如selected,href,src等那么调用内部的set方法或者get方法 //如jQuery.propHooks["select"]就是内置的对象 name = jQuery.propFix[ name ] || name; hooks = jQuery.propHooks[ name ]; } //如果value不为空表示设置 if ( value !== undefined ) { //设置成功返回set方法的返回值,否则返回elem的相应属性.但是必须注意:这里的propHooks里面的属性是固定的 return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ? ret :( elem[ name ] = value ); } else { //获取相应属性 return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ? ret : elem[ name ]; } },
propFix:对tabindex等进行的处理
jQuery.each([ "tabIndex", "readOnly", "maxLength", "cellSpacing", "cellPadding", "rowSpan", "colSpan", "useMap", "frameBorder", "contentEditable" ], function() { jQuery.propFix[ this.toLowerCase() ] = this; });
IE6/7下面enctype是encoding
// IE6/7 call enctype encoding if ( !support.enctype ) { jQuery.propFix.enctype = "encoding"; }for修改为htmlFor,class是className,所以对于prop方法来说可以传入for也可以传入htmlFor等
propFix: { "for": "htmlFor", "class": "className" }
tabIndex来说jQuery做了特殊的处理,也就是说我们获取tabIndex的时候是调用该hooks中的get!
var rfocusable = /^(?:input|select|textarea|button|object)$/i, rclickable = /^(?:a|area)$/i; propHooks: { tabIndex: { get: function( elem ) { // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ // Use proper attribute retrieval(#12072) var tabindex = jQuery.find.attr( elem, "tabindex" );//因为tabIndex如果没有设置可能会返回不正确的值! //这里还是调用jQueyr.find.attr方法,不过传入的不是驼峰写法!如果调用该方法没有获取到有效的tabIndex //那么要对标签进行判断,如果是input/select/textarea/button/object那么返回0;如果是a/area同时有href //也返回0,否则返回-1! return tabindex ? parseInt( tabindex, 10 ) : rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? 0 : -1; } }//End of tabIndex } });对hrefNormalize进行分析:该方法判断是否能够获取到有效的href值!如果是返回true!
div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>"; a = div.getElementsByTagName("a")[ 0 ]; support.hrefNormalized = a.getAttribute("href") === "/a";
如果不能获取到有效的href属性值,那么我们用getAttribute("href")或者getAttribute("src")等,至于为什么加入第二个参数是为了在IE6/7下获取完整的src/href属性!
//如果获取hooks是undefined,那么直接返回elem[key]的值! //我们看看jQuery中对propHooks进行设置的代码: //代码一之href和src: if ( !support.hrefNormalized ) { // href/src property should get the full normalized URL (#10299/#12915) jQuery.each([ "href", "src" ], function( i, name ) { jQuery.propHooks[ name ] = { get: function( elem ) { return elem.getAttribute( name, 4 ); } }; });
optSelected属性测试:
// Make sure that a selected-by-default option has a working selected property. // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) select = document.createElement("select"); opt = select.appendChild( document.createElement("option") ); support.optSelected = opt.selected;检测当一个option添加到select上时候该option是否被选中,也就是他的selected是否是true,如果是true表示被选中,如果是false表示没有被选中!如果没有被选中的时候我们要做兼容!也就是默认第一项被选中!
// Support: Safari, IE9+ // mis-reports the default selected property of an option // Accessing the parent's selectedIndex property fixes it //IE9+和Safari会错误的得到option的默认的selected属性,通过获取他父元素的selectedIndex解决这个bug if ( !support.optSelected ) { jQuery.propHooks.selected = { get: function( elem ) { var parent = elem.parentNode; if ( parent ) { parent.selectedIndex; // Make sure that it also works with optgroups, see #5701 if ( parent.parentNode ) { parent.parentNode.selectedIndex; } } return null;//返回null,所以在prop方法里最后返回的还是elem["selected"] } }; }jQuery中暂时没有找到其它的地方对jQuery.propHooks进行赋值。设置值的时候这个hook不存在,那么就会 调用elem[key]=value进行赋值!但是在attr方法中调用的是setAttribute方法!
(1)如果使用prop()
函数操作表单元素的checked
、selected
、disabled
等属性,如果该元素被选中(或禁用),则返回true
,否则(意即HTML中没有该属性)返回false
。之所以是这样还是因为底层用的是property访问的方法,不是用getAttribute方法!不选中的时候property返回false,attribute返回null!
(2)prop()
函数还可以设置或返回DOM元素的Element
对象上的某些属性,例如:tagName、selectedIndex、nodeName、nodeType、ownerDocument、defaultChecked和defaultSelected等属性。之所以能够获取是因为每一个元素在firebug下都能看到这个property!是property不是attributes,而且这些属性是不能被改变的,也就是说如果你把tagName设置为新的值,那么再次获取还是原来的值!
(3)在IE9及更早版本中,如果使用prop()
函数设置的属性值不是一个简单的原始值(String、Number、Boolean),并且在对应的DOM元素被销毁之前,该属性没有被移除,则可能会导致内存泄漏问题。如果你只是为了存储数据,建议你使用data()函数,以避免内存泄漏问题。
(4)但是从1.6开始,使用attr()
获取这些属性的返回值为String类型,如果被选中(或禁用)就返回checked
、selected
或disabled
,否则(即元素节点没有该属性)返回undefined
。并且,在某些版本中,这些属性值表示文档加载时的初始状态值,即使之后更改了这些元素的选中(或禁用)状态,对应的属性值也不会发生改变。1.11.1就是这样
(5)因为tabIndex如果没有设置可能会返回不正确的值!这里还是调用jQueyr.find.attr方法,不过传入的不是驼峰写法!如果调用该方法没有获取到有效的tabIndex那么要对标签进行判断,如果是input/select/textarea/button/object那么返回0;如果是a/area同时有href也返回0,否则返回-1!
(6)如果用prop方法访问for属性,可以用htmlFor也可以用for,因为prop方法有专门针对他的propFix,如果用attr访问for属性那么就只能是attr("for"),对于class也是一样的!(记住:这时候prop方法要变成驼峰)
(7)针对IE6/7获取URL会被修改的情况下,IE调用getAttribute方法时候传入了第二个参数为4,那么就能和其它浏览器一样不会串改URL!