.prop() vs .attr()

.prop() vs .attr()

技术背景

在jQuery 1.6之前,attr()方法在获取某些属性时有时会考虑属性值,这导致了相当不一致的行为。为了解决这个问题,jQuery 1.6引入了prop()方法,它提供了一种显式检索属性值的方式,而.attr()则用于检索属性。理解prop()attr()的区别对于正确处理HTML属性和DOM属性至关重要。

实现步骤

理解HTML属性和DOM属性

  • HTML属性:存在于HTML文本文件中,用于为标记关联数据,例如事件、渲染等。属性以字符串形式返回,不同浏览器可能存在不一致性。例如:
1
<body onload="foo()">

可以通过以下代码访问属性:

1
2
3
4
var attr;
attr = document.body.getAttribute("class");
//IE 8 Quirks和更低版本
attr = document.body.getAttribute("className");
  • DOM属性:属于元素节点的属性,只能通过JavaScript访问。例如:
1
document.body.onload = foo;

区分.prop().attr()的使用场景

  • 大部分情况使用.prop():属性通常比属性更容易处理,属性值可以是任何类型,而属性值只能是字符串。例如,checked属性是布尔值,style属性是一个对象。
  • 特定情况使用.attr():当没有与之相关的属性(自定义属性),或者知道该特定属性与属性不是1:1对应时,使用.attr()。例如,获取自定义的data-xyz属性。

示例演示

1
<input id="cb" type="checkbox" checked>
1
2
3
4
5
6
7
8
9
10
11
// 使用.attr()检查复选框是否选中
if ($("#cb").attr("checked") === true) {...}
if ($("#cb").attr("checked") == "checked") {...}
if ($("#cb").is(":checked")) {...}

// 使用.prop()检查复选框是否选中
if (document.getElementById("cb").checked) {...}

// 使用.prop()取消选中复选框
document.getElementById("cb").checked = false;
$("#cb").prop("checked", false);

核心代码

检查属性和属性值

1
2
3
const link = document.getElementById("fooAnchor");
console.log(link.href); // 显示 "http://example.com/foo.html"
console.log(link.getAttribute("href")); // 显示 "foo.html"

比较.attr().prop()

1
2
3
4
5
$('input').attr('blah', 'apple');
$('input').prop('blah', 'pear');

console.log($('input').attr('blah')); // 返回 'apple'
console.log($('input').prop('blah')); // 返回 'pear'

检查复选框状态

1
2
3
4
$('button').on('click', function() {
$('#attr').attr('checked', 'checked');
$('#prop').prop('checked', true);
});

最佳实践

  • 优先使用.prop():在大多数情况下,使用.prop()来处理属性,因为它更直接地影响有效属性,而不是依赖于修改HTML的复杂副作用。
  • 使用.attr()处理自定义属性:当需要获取自定义HTML属性或与DOM属性不同步的HTML属性时,使用.attr()
  • 避免混合使用:在整个应用程序中,不要为同一属性混合使用.attr().prop()

常见问题

1. .attr().prop()返回值类型不同

.attr()总是返回字符串,而.prop()可以返回任何类型,如字符串、整数、布尔值等。

2. 性能差异

.prop()据说比.attr()快约2.5倍。

3. 复选框状态问题

使用.attr('checked')可能无法正确反映复选框的当前状态,而.prop('checked')可以。

4. CSS选择器问题

.attr()可以影响所有属性选择器,而.prop()只影响少数属性选择器。