jQuery 中 attr 和 prop 方法的区别

 我来答
受司大人
2015-02-16 · 知道合伙人影视综艺行家
受司大人
知道合伙人影视综艺行家
采纳数:20262 获赞数:171846
毕业于浙江广厦,有一定的电脑专业基础和两年工作经验,读过相关书籍多本

向TA提问 私信TA
展开全部
一直都在用 jQuery 1.8.3 的版本,没有尝试过 jQuery 1.9.0 的版本。
于是,开始调试代码,在 1.9.0 的版本中:
<input type="checkbox" />
<script>
$(function() {
$('input').click(function() {
$(this).attr('checked');
});
});
</script>

点击 checkbox,结果都是 undefined
而在 1.8.3 的版本中,结果是 checked 和 undefined
到这里,问题答案找到了,就是使用 attr() 方法的问题,于是查看官方文档, 才知道从 jQuery 1.6 开始新增了一个方法 prop(),但是一直都没有使用过。
从中文意思看,两者分别是获取/设置 attributes 和 properties 的方法,那么为什么还要增加 prop() 方法呢?
Before jQuery 1.6, the .attr() method sometimes took property values into account when retrieving some attributes, which could cause inconsistent behavior.

因为在 jQuery 1.6 之前,使用 attr() 有时候会出现不一致的行为。
那么,什么时候使用attr(),什么时候使用prop()?
To retrieve and change DOM properties such as the checked, selected, or disabled state of form elements, use the .prop() method.

根据官方的建议:具有 true 和 false 两个属性的属性,如 checked, selected 或者 disabled 使用prop(),其他的使用 attr()
到此,将 attr('checked') 改成 prop('checked') 即可修复提的 issues 了。
^_^
等等,貌似问题还没真正解决,为什么开头例子中 jQuery 1.8.3 和 1.9.0 使用 attr() 会有所区别呢?
想知道他们的区别,最好的办法还是看他们的源代码:
1.8.3 attr():
attr: function( elem, name, value, pass ) {
var ret, hooks, notxml,
nType = elem.nodeType;

// don't get/set attributes on text, comment and attribute nodes
if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
return;
}

if ( pass && jQuery.isFunction( jQuery.fn[ name ] ) ) {
return jQuery( elem )[ name ]( value );
}

// Fallback to prop when attributes are not supported
if ( typeof elem.getAttribute === "undefined" ) {
return jQuery.prop( elem, name, value );
}

notxml = nType !== 1 || !jQuery.isXMLDoc( elem );

// All attributes are lowercase
// Grab necessary hook if one is defined
if ( notxml ) {
name = name.toLowerCase();
hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );
}

if ( value !== undefined ) {

if ( value === null ) {
jQuery.removeAttr( elem, name );
return;

} else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {
return ret;

} else {
elem.setAttribute( name, value + "" );
return value;
}

} else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {
return ret;

} else {

ret = elem.getAttribute( name );

// Non-existent attributes return null, we normalize to undefined
return ret === null ?
undefined :
ret;
}
}

1.9.0 attr():
attr: function( elem, name, value ) {
var ret, hooks, notxml,
nType = elem.nodeType;

// don't get/set attributes on text, comment and attribute nodes
if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
return;
}

// Fallback to prop when attributes are not supported
if ( typeof elem.getAttribute === "undefined" ) {
return jQuery.prop( elem, name, value );
}

notxml = nType !== 1 || !jQuery.isXMLDoc( elem );

// All attributes are lowercase
// Grab necessary hook if one is defined
if ( notxml ) {
name = name.toLowerCase();
hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );
}

if ( value !== undefined ) {

if ( value === null ) {
jQuery.removeAttr( elem, name );

} else if ( hooks && notxml && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
return ret;

} else {
elem.setAttribute( name, value + "" );
return value;
}

} else if ( hooks && notxml && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
return ret;

} else {

// In IE9+, Flash objects don't have .getAttribute (#12945)
// Support: IE9+
if ( typeof elem.getAttribute !== "undefined" ) {
ret = elem.getAttribute( name );
}

// Non-existent attributes return null, we normalize to undefined
return ret == null ?
undefined :
ret;
}
}

1.8.3 和 1.9.0 的 prop() 是一样的:
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;
}

notxml = nType !== 1 || !jQuery.isXMLDoc( elem );

if ( notxml ) {
// Fix name and attach hooks
name = jQuery.propFix[ name ] || name;
hooks = jQuery.propHooks[ name ];
}

if ( value !== undefined ) {
if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
return ret;

} else {
return ( elem[ name ] = value );
}

} else {
if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
return ret;

} else {
return elem[ name ];
}
}
}

首先,我们看下 attr() 和 prop() 的区别:
attr() 里面,最关键的两行代码
elem.setAttribute( name, value + "" );

ret = elem.getAttribute( name );

很明显的看出来,使用的 DOM 的 API setAttribute() 和 getAttribute() 方法操作的属性元素节点。
prop() 里面,最关键的两行代码
return ( elem[ name ] = value );

return elem[ name ];

可以理解为 document.getElementById(el)[name] = value,这是转化成 element 的一个属性。
对比调试 1.9.0 和 1.8.3 的 attr() 方法,发现两者的区别在于
hooks.get( elem, name ))

返回的值不一样,具体的实现:
1.8.3 中
boolHook = {
get: function( elem, name ) {
// Align boolean attributes with corresponding properties
// Fall back to attribute presence where some booleans are not supported
var attrNode,
property = jQuery.prop( elem, name );
return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?
name.toLowerCase() :
undefined;
}
}

1.9.0 中
boolHook = {
get: function( elem, name ) {
var
// Use .prop to determine if this attribute is understood as boolean
prop = jQuery.prop( elem, name ),

// Fetch it accordingly
attr = typeof prop === "boolean" && elem.getAttribute( name ),
detail = typeof prop === "boolean" ?

getSetInput && getSetAttribute ?
attr != null :
// oldIE fabricates an empty string for missing boolean attributes
// and conflates checked/selected into attroperties
ruseDefault.test( name ) ?
elem[ jQuery.camelCase( "default-" + name ) ] :
!!attr :

// fetch an attribute node for properties not recognized as boolean
elem.getAttributeNode( name );

return detail && detail.value !== false ?
name.toLowerCase() :
undefined;
}
}

由此可见,1.9.0 开始不建议使用 attr() 来对具有 true 和 false 两个属性的属性进行操作了。
百度网友080b03f
2015-02-16 · TA获得超过463个赞
知道小有建树答主
回答量:381
采纳率:100%
帮助的人:283万
展开全部
  1. selectedIndex, tagName, nodeName,
    nodeType, ownerDocument, defaultChecked,
    and defaultSelected 等属性应使用prop获取和设定

  2. prop可以直接获取boolean属性,例如$(elem).prop("checked") 为true、false, 而不是字符串'checked'

已赞过 已踩过<
你对这个回答的评价是?
评论 收起
Baby_原來
推荐于2016-03-29 · TA获得超过3402个赞
知道大有可为答主
回答量:1535
采纳率:94%
帮助的人:503万
展开全部
--区别
使用prop的时候,返回值是标准属性,true/false,比如$('#checkbox').prop('disabled'),不会返回“disabled”或者“”,只会是true/false。当然赋值的时候也是如此。

使用attr,如disabled='disabled'时,为true,没有选中时,则为undefined。如此,便统一了所有操作,无论是从语法上还是语义上。

.prop方法应该被用来处理boolean attributes/properties以及在html(比如:window.location)中不存在的properties。

其他所有的attributes可以而且应该继续使用.attr()方法来进行操作。

--使用
1、添加属性名称该属性就会生效应该使用prop();
2、是有true,false两个属性使用prop();
3、其他则使用attr();
4、简单的说,那些只添加属性名不添加属性值就会生效,或者是,只存在true/false的属性就需要使用prop()方法,比如selectedIndex, tagName, nodeName, nodeType, ownerDocument, defaultChecked, 和 defaultSelected。
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
djchallenge
2015-02-16 · 超过25用户采纳过TA的回答
知道答主
回答量:119
采纳率:0%
帮助的人:64.9万
展开全部
attr是1.9之前的写法,不存在prop
prop是之后的写法,但attr也可以使用
用的时候注意版本差异就行了
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 更多回答(2)
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式