前几天,有人给 Multiple Select 插件 提了问题:

setSelects doesn't work in Firefox when using jquery 1.9.0

一直都在用 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 两个属性的属性进行操作了。

那么我们的结论是:

具有 true 和 false 两个属性的属性,如 checked, selected 或者 disabled 使用prop(),其他的使用 attr(),具体见下表:


注:本文中的大部分观点以及例子属于个人理解,难免还有不准确的地方,欢迎有相关研究的同行指正。

jQuery 中 attr() 和 prop() 方法的区别的更多相关文章

  1. jQuery中attr和prop方法的区别

    jQuery中attr和prop方法的区别。 http://my.oschina.net/bosscheng/blog/125833 http://www.javascript100.com/?p=8 ...

  2. jQuery中attr和prop方法的区别说明

    jquery中attr和prop的基本区别可以理解为:如果是内置属性,建议用prop,如果是自定义的建议用attr. 例如 <input type=check  node=123 id=ck & ...

  3. jQuery 中 attr() 和 prop() 方法的区别<转>

    前几天,有人给 Multiple Select 插件 提了问题: setSelects doesn't work in Firefox when using jquery 1.9.0 一直都在用 jQ ...

  4. jquery中attr和prop的区别、 什么时候用 attr 什么时候用 prop (转自 芈老头 )

    jquery中attr和prop的区别. 什么时候用 attr 什么时候用 prop   在高版本的jquery引入prop方法后,什么时候该用prop?什么时候用attr?它们两个之间有什么区别?这 ...

  5. jQuery中.attr()和.prop()的区别

    之前学习jQuery的时候,学习到了两种取得标签的属性值的方法:一种是elemJobj.attr(),另一种是elemJobj.prop().而在学习JS的时候,只有一种方法elemObj.getAt ...

  6. jquery中attr和prop的区别(转)

    在网络上看到这样一篇关于jquery中attr和prop的区别文章,觉得不错,所以转载了. 在jQuery 1.6中,.attr()方法查询那些没有设置的属性,则会返回一个undefined.如果你要 ...

  7. jquery中attr()与prop()函数用法实例详解(附用法区别)

    本文实例讲述了jQuery中attr()与prop()函数用法.分享给大家供大家参考,具体如下: 一.jQuery的attr()方法 jquery中用attr()方法来获取和设置元素属性,attr是a ...

  8. jquery中attr和prop的区别分析

    这篇文章主要介绍了jquery中attr和prop的区别分析的相关资料,需要的朋友可以参考下 在高版本的jquery引入prop方法后,什么时候该用prop?什么时候用attr?它们两个之间有什么区别 ...

  9. Jquery学习笔记(6)--jquery中attr和prop的区别【精辟】

    jquery中attr和prop的区别 在高版本的jquery引入prop方法后,什么时候该用prop?什么时候用attr?它们两个之间有什么区别?这些问题就出现了. 关于它们两个的区别,网上的答案很 ...

随机推荐

  1. [转] linux 下查看一个进程运行路径的方法

    http://blog.csdn.net/brioxu/article/details/5104736 在linux下查看进程大家都会想到用 ps -ef|grep XXX ps -aux | hea ...

  2. 拓展企业VR培训业务,这家VR训练公司StriVR完成500万美元融资!

    虚拟现实初创公司StriVR最近发布了新的企业VR训练产品项目,并宣布在刚刚结束的首轮融资中获得500万美元投资.由Signia Venture Partners领投,宝马i Venturesi.Ad ...

  3. gson 简要使用

    http://www.cnblogs.com/chenlhuaf/archive/2011/05/01/gson_test.html 发现了google的gson,因为之前对于protocolbuf有 ...

  4. CF 256D. Good Sequences(DP)

    题目链接 主要是标记前面素数的最大的DP值,要认真一些.没想到居然写了一个很难发现的错误. #include <cstdio> #include <cstring> #incl ...

  5. OSG 自定义数据类型 关键帧动画

    OSG 自定义数据类型 关键帧动画 转自:http://blog.csdn.net/zhuyingqingfen/article/details/12651017 /* 1.创建一个AnimManag ...

  6. C# using的一些事

    一.using释放资源 using不可以释放所有的对象,原因如下: 1.using可以主动释放的对象都需要实现IDisable接口. 2.即使都实现了IDisable接口,也没有必要全部使用using ...

  7. hdu杭电1671 / poj3630 字典树

    传送门 题意:输入n串数字 找出是否有存在串的前缀与另一个串相同 如果存在 输出NO否则输出YES 思路:用字典树解决 标记字典树总串的结尾 查找出一个串内部是否有被标记的节点 如果有那么说明存在前缀 ...

  8. openoffice从word转pdf问题

    http://www.oschina.net/question/227511_87517

  9. bzoj4562: [Haoi2016]食物链--记忆化搜索

    这道题其实比较水,半个小时AC= =对于我这样的渣渣来说真是极大的鼓舞 题目大意:给出一个有向图,求入度为0的点到出度为0的点一共有多少条路 从入读为零的点进行记忆化搜索,搜到出度为零的点返回1 所有 ...

  10. centos6 搭建ELK

    mark一下时间:2016年2月19日10:17:09 记录使用 Logstash: Logstash服务的组件,用于处理传入的日志. Elasticsearch: 存储所有日志 Kibana 4: ...