.prop()vs .attr()

Nea*_*eal 2249 javascript jquery dom prop attr

所以jQuery 1.6具有新功能prop().

$(selector).click(function(){
    //instead of:
    this.getAttribute('style');
    //do i use:
    $(this).prop('style');
    //or:
    $(this).attr('style');
})
Run Code Online (Sandbox Code Playgroud)

或者在这种情况下,他们做同样的事情?

如果我有转用prop(),所有的旧attr()电话,如果我切换到1.6将打破?

UPDATE

selector = '#id'

$(selector).click(function() {
    //instead of:
    var getAtt = this.getAttribute('style');
    //do i use:
    var thisProp = $(this).prop('style');
    //or:
    var thisAttr = $(this).attr('style');

    console.log(getAtt, thisProp, thisAttr);
});
Run Code Online (Sandbox Code Playgroud)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.0/jquery.min.js"></script>
<div id='id' style="color: red;background: orange;">test</div>
Run Code Online (Sandbox Code Playgroud)

(另见这个小提琴:http://jsfiddle.net/maniator/JpUF2/)

控制台会记录getAttribute作为一个字符串,并attr作为一个字符串,但prop作为一个CSSStyleDeclaration,为什么?这对我未来的编码有何影响?

Tim*_*own 1854

2012年11月1日更新

我的原始答案特别适用于jQuery 1.6.我的建议仍然保持不变,但jQuery 1.6.1略有改变:面对预测的一堆破碎的网站,jQuery团队恢复attr()了与布尔属性的旧行为接近(但不完全相同)的东西.John Resig也在博客上写了这篇文章.我可以看到他们遇到的困难,但仍然不同意他的偏好建议attr().

原始答案

如果您只使用过jQuery而不是直接使用DOM,那么这可能是一个令人困惑的变化,尽管它在概念上肯定是一种改进.对于使用jQuery的网站来说,这不太好,但是由于这种变化会破坏.

我将总结主要问题:

  • 你通常想要prop()而不是attr().
  • 在大多数情况下,prop()做什么attr()用的事情.在代码中替换对attr()with的调用prop()通常会起作用.
  • 属性通常比属性更容易处理.属性值可以只是一个字符串,而属性可以是任何类型.例如,checked属性是布尔值,style属性是一个对象,每个样式都有各自的属性,size属性是一个数字.
  • 如果属性和具有相同名称的属性都存在,通常更新一个将更新另一个,但输入的某些属性不是这种情况,例如valuechecked:对于这些属性,属性始终表示当前状态,而属性(旧版本的IE除外)对应于输入的默认值/ checkedness(反映在defaultValue/ defaultCheckedproperty中).
  • 这个更改删除了一些在属性和属性前面停留的魔法jQuery层,这意味着jQuery开发人员必须要了解一下属性和属性之间的区别.这是一件好事.

如果你是一个jQuery开发人员并且对整个业务的属性和属性感到困惑,那么你需要退后一步并学习一点,因为jQuery不再那么努力地保护你不受这些东西的影响.对于关于这个主题的权威但有点干的词,有规格:DOM4,HTML DOM,DOM Level 2,DOM Level 3.Mozilla的DOM文档对大多数现代浏览器都有效,并且比规范更容易阅读,因此您可能会发现他们的DOM参考有用.有一个关于元素属性部分.

作为属性如何比属性更易于处理的示例,请考虑最初检查的复选框.以下是两个可能的有效HTML片段:

<input id="cb" type="checkbox" checked>
<input id="cb" type="checkbox" checked="checked">
Run Code Online (Sandbox Code Playgroud)

那么,你怎么知道是否用jQuery检查了复选框?查看Stack Overflow,您通常会找到以下建议:

  • if ( $("#cb").attr("checked") === true ) {...}
  • if ( $("#cb").attr("checked") == "checked" ) {...}
  • if ( $("#cb").is(":checked") ) {...}

这实际上是世界上最简单的事情,checked布尔属性自1995年以来在每个主要的可编写脚本的浏览器中都存在并且完美无缺:

if (document.getElementById("cb").checked) {...}

该属性还可以检查或取消选中复选框:

document.getElementById("cb").checked = false

在jQuery 1.6中,这毫不含糊地变成了

$("#cb").prop("checked", false)

使用该checked属性来编写复选框脚本的想法是无益的,也是不必要的.该物业是您所需要的.

  • 检查或取消选中复选框的正确方法是使用该checked属性,这一点并不明显
  • 属性值反映默认值而不是当前可见状态(除了IE的某些旧版本,因此使事情变得更加困难).该属性不会告诉您是否选中了页面上的复选框.见http://jsfiddle.net/VktA6/49/.

  • @Neal:DOM元素是一个对象.属性是该对象的属性,就像任何其他编程对象一样.其中一些道具从标记中的属性获取其初始值,这些属性也存储在DOM对象的*separate*属性映射中.在大多数情况下,写入道具只会改变道具,虽然遗憾的是有一些道具会将任何变化写入底层的attr(例如"值"),但让我们试着大多忽略它.99%的时间,你想使用道具.如果您需要使用实际属性,您可能会知道这一点. (53认同)
  • @Neal:如果你想知道DOM元素具有哪些属性以及属性如何为其值设定种子,请保持这些链接:[DOM2 HTML规范](http://www.w3.org/TR/DOM-Level- 2-HTML /),[DOM2](http://www.w3.org/TR/DOM-Level-2-Core/)规范和[DOM3](http://www.w3.org/TR/DOM-Level-3-Core /)规范.每种情况下的指数都非常出色,可以直接将您的财产直接描述,其价值来自哪里,等等. (9认同)
  • `$('#chk').checked`**从不**工作......这根本不是合适的jQuery ... (5认同)
  • @Neal:Re使它与众不同:信息的来源和性质.例如,看看蒂姆的"价值"例子.一个名为`attr`的函数检索*property*`value`而不是属性"value"没有多大意义(并且它们可以不同).继续前进,`attr`做属性和`prop`做属性会更清楚,虽然过渡对某些人来说会很痛苦.不要采取错误的方式,没有什么比回过头来阅读规范以了解属性是什么. (4认同)
  • @Tim:*"更改输入的`value`属性不会改变现代浏览器中的`value`属性"*我认为没有,这就是为什么我开始使用它作为一个例子,但是当我开始编写示例代码,如果它没有在Chrome,Firefox,Opera,IE上更新,那就大胆了... - http://jsbin.com/ahire4原来那是因为我使用的是`input [type ="按钮"]`用于我的实验.它*不会*更新`input [type ="text"]的属性` - http://jsbin.com/ahire4/2谈论复杂的!! 不只是元素,而是它的*类型*... (4认同)
  • @TJCrowder,那么哪些? (2认同)
  • @TJCrowder你能否给出一个完整的答案,而不是这些破碎的评论?对于未来的用户来说,它可能更容易阅读 (2认同)

T.J*_*der 659

我认为蒂姆说得很好,但让我们退后一步:

DOM元素是一个对象,一个在内存中的东西.与OOP中的大多数对象一样,它具有属性.它还单独包含元素上定义的属性的映射(通常来自浏览器读取以创建元素的标记).有些元素的属性得到他们最初从值属性具有相同或相似名称(value从"值"属性获取其初始值; href从"href"属性获取其初始值,但它不是完全一样的值; className从"阶级"属性).其他属性以其他方式获取其初始值:例如,parentNode属性根据其父元素获取其值; 元素始终具有style属性,无论它是否具有"样式"属性.

让我们在页面中考虑这个锚http://example.com/testing.html:

<a href='foo.html' class='test one' name='fooAnchor' id='fooAnchor'>Hi</a>
Run Code Online (Sandbox Code Playgroud)

一些无偿的ASCII艺术(并遗漏了很多东西):

+???????????????????????????????????????????+
|             HTMLAnchorElement             |
+???????????????????????????????????????????+
| href:       "http://example.com/foo.html" |
| name:       "fooAnchor"                   |
| id:         "fooAnchor"                   |
| className:  "test one"                    |
| attributes:                               |
|    href:  "foo.html"                      |
|    name:  "fooAnchor"                     |
|    id:    "fooAnchor"                     |
|    class: "test one"                      |
+???????????????????????????????????????????+

请注意,属性和属性是不同的.

现在,尽管它们是截然不同的,因为所有这些都是从头开始设计的,而不是从头开始设计,如果你设置它们,许多属性会回写它们派生的属性.但并非所有人都这样做,而且从href上面可以看出,映射并不总是直接"传递价值",有时会涉及到解释.

当我谈到属性是对象的属性时,我不是在抽象地说.这是一些非jQuery代码:

var link = document.getElementById('fooAnchor');
alert(link.href);                 // alerts "http://example.com/foo.html"
alert(link.getAttribute("href")); // alerts "foo.html"
Run Code Online (Sandbox Code Playgroud)

(这些值与大多数浏览器一样;有一些变化.)

link物体是一个真实的东西,你可以看到有访问之间的真正的区别属性就可以了,和访问的属性.

蒂姆说,绝大多数时候,我们都希望与房地产合作.部分原因是因为它们的值(甚至是它们的名称)在浏览器中往往更加一致.我们大多只希望在没有与之相关的属性(自定义属性)时使用属性,或者当我们知道对于该特定属性时,属性和属性不是1:1(与href上面的"href"一样) .

标准属性在各种DOM规范中列出:

这些规格有很好的索引,我建议保持链接方便; 我一直都在使用它们.

例如,自定义属性包括data-xyz您可能放置在元素上的任何属性,以便为您的代码提供元数据(现在,只要您坚持使用data-前缀,该属性就像HTML5一样有效).(jQuery的的最新版本给你访问data-xyz通过要素data的功能,但该功能是不是只是一个访问data-xyz属性[它都越来越小于];除非你真正需要它的特点,我会使用的attr功能互动有data-xyz属性.)

这个attr函数过去常常有一些错综复杂的逻辑来获得他们想要的东西,而不是字面上得到属性.它混淆了这些概念.移动到prop并且attr意味着去除它们.简要V1.6.0 jQuery的去在这方面太远,但功能迅速添加回attr处理人们使用常见的情况attr时,技术上应该使用prop.

  • @TJCrowder re:`.data` - 它将_read_属性的默认值(如果存在),但如果你写它,它将改变元素的隐藏_property_,而不是更新属性. (3认同)

小智 249

jQuery已经有很长一段时间了.多年来,他们一直满足于一个名为attr()主要检索DOM属性的函数,而不是您期望从名称中得到的结果.隔离attr()prop()应该有助于缓解HTML属性和DOM属性之间的一些混淆.$.fn.prop()获取指定的DOM属性,同时$.fn.attr()获取指定的HTML属性.

为了完全理解它们是如何工作的,这里是对HTML属性和DOM属性之间差异的扩展解释:

HTML属性

句法:

<body onload="foo()">

目的: 允许标记为事件,呈现和其他目的提供与之关联的数据.

可视化: HTML属性 class属性显示在正文中.可通过以下代码访问:

var attr;
attr = document.body.getAttribute("class");
//IE 8 Quirks and below
attr = document.body.getAttribute("className");
Run Code Online (Sandbox Code Playgroud)

属性以字符串形式返回,并且从浏览器到浏览器可能不一致.但是,它们在某些情况下至关重要.如上所示,IE 8 Quirks Mode(及以下)需要get/set/removeAttribute中DOM属性的名称而不是属性名称.这是了解差异的重要原因之一.

DOM属性

句法:

document.body.onload = foo;

目的: 提供对属于元素节点的属性的访问.这些属性与属性类似,但只能通过JavaScript访问.这是一个重要的区别,有助于阐明DOM属性的作用.请注意,属性与属性完全不同,因为此事件处理程序分配是无用的,并且不会接收事件(正文没有onload事件,只有onload属性).

可视化: DOM属性

在这里,您将注意到Firebug中"DOM"选项卡下的属性列表.这些是DOM属性.你会立刻注意到它们中的很多,因为你以前会在不知情的情况下使用它们.他们的价值观是你通过JavaScript获得的.

文档

HTML: <textarea id="test" value="foo"></textarea>

JavaScript的: alert($('#test').attr('value'));

在早期版本的jQuery中,这将返回一个空字符串.在1.6中,它返回正确的值,foo.

在没有浏览任何一个函数的新代码的情况下,我可以充满信心地说,混淆更多地与HTML属性和DOM属性之间的差异有关,而不是与代码本身有关.希望这能为你解决一些问题.

-Matt

  • 男孩,我现在也很困惑.所以`$('#test').prop('value')`什么都不返回?`.attr('checked')`也没有复选框?但它习惯了吗?现在你必须把它改成'prop('checked')`?我不明白这种区别的必要性 - 为什么区分HTML属性和DOM属性很重要?什么是使这种变化"很长一段时间"的常见用例*?什么是*错误*抽象两者之间的区别,因为看起来他们的用例大多重叠? (10认同)
  • `$ .prop()`获取DOM属性,`$ .attr()`获取HTML属性.我试图在心理上弥合差距所以你可以理解两者之间的差异. (7认同)
  • @BlueRaja:因为这两个概念之间存在严重的潜在差异,如果你像jQuery一样在地毯上刷它,会导致意外的失败.`value`是最明显的情况之一,因为`value`属性将为您提供字段的当前值,但`value`属性将为您提供在`value ="中声明的原始值. "`属性,实际上是`defaultValue`属性.(虽然这个特殊情况再次被IE <9中的错误搞糊涂了.) (5认同)
  • @BlueRaja:答案更复杂.:-)在jQuery <1.6中设置`attr('value',...)`设置属性,所以当前值改变而默认值不改变.在1.6中它设置了属性,因此理论上默认值会改变,而当前值则不会.但是,有(更多)浏览器与`value`属性的确切设置不一致.在IE中它也设置当前值; 在某些浏览器中,如果之前尚未设置当前值,则仅设置当前值.[呼喊] (4认同)

yun*_*zen 240

属性在DOM中; HTML中的属性被解析为DOM.

更多细节

如果更改属性,则更改将反映在DOM中(有时使用不同的名称).

示例:更改class标记的属性将更改classNameDOM中该标记的属性.如果标记上没有属性,则仍然具有相应的DOM属性,其属性为空或默认值.

示例:虽然您的标记没有class属性,但DOM属性className确实存在,并且字符串值为空.

编辑

如果更改一个,则另一个将由控制器更改,反之亦然.这个控制器不在jQuery中,而是在浏览器的本机代码中.

  • "如果你更改了一个,另一个将由控制器更改,反之亦然.这个控制器不在jQuery中,而是在浏览器的本机代码中." 对于大多数属性/属性,这不是**.对于大多数,它只是单向转换,其中属性确定相应属性的_initial_值.前两个答案详细解释了这一点. (3认同)

Gar*_*een 139

只是HTML属性和DOM对象之间的区别导致混淆.对于那些舒服作用于DOM元素本地特性这样的this.src this.value this.checked等,.prop是一个非常热烈的欢迎家庭.对于其他人来说,这只是一层混乱.让我们清楚一点.

最简单的方法,看看之间的区别.attr,并.prop为下面的例子:

<input blah="hello">
Run Code Online (Sandbox Code Playgroud)
  1. $('input').attr('blah'):'hello'按预期返回.这里没有惊喜.
  2. $('input').prop('blah'):返回undefined- 因为它正在尝试[HTMLInputElement].blah- 并且该DOM对象上不存在此类属性.它仅作为该元素的属性存在于范围中,即[HTMLInputElement].getAttribute('blah')

现在我们改变一些事情:

$('input').attr('blah', 'apple');
$('input').prop('blah', 'pear');
Run Code Online (Sandbox Code Playgroud)
  1. $('input').attr('blah'):回来'apple'呃?为什么不在这个元素上设置"梨".因为属性是在输入属性上更改的,而不是DOM输入元素本身 - 它们基本上几乎彼此独立工作.
  2. $('input').prop('blah'):返回 'pear'

你真正需要注意的事情就是不要因为上述原因而在整个应用程序中混合使用这些属性.

看一个展示差异的小提琴: http ://jsfiddle.net/garreh/uLQXc/


.attrvs .prop:

第1轮:风格

<input style="font:arial;"/>
Run Code Online (Sandbox Code Playgroud)
  • .attr('style') - 返回匹配元素的内联样式,即 "font:arial;"
  • .prop('style') - 返回样式声明对象,即 CSSStyleDeclaration

第二轮:价值

<input value="hello" type="text"/>   

$('input').prop('value', 'i changed the value');
Run Code Online (Sandbox Code Playgroud)
  • .attr('value')- 退货'hello'*
  • .prop('value') - 退货 'i changed the value'

*注意:jQuery因此有一个.val()方法,内部相当于.prop('value')

  • 似乎与doc,http://api.jquery.com/prop/不同:".prop()方法应该用于设置disabled和checked而不是.attr()方法..val()方法应该被用来获取和设定价值." (2认同)

agj*_*lls 52

TL; DR

使用prop()attr()在大多数情况下.

属性是输入元件的当前状态.一个属性是默认值.

属性可以包含不同类型的东西.属性只能包含字符串


Cir*_*四事件 36

肮脏的检查

这个概念提供了一个可以观察到差异的例子:http://www.w3.org/TR/html5/forms.html#concept-input-checked-dirty

试试看:

  • 单击按钮.两个复选框都已选中.
  • 取消选中这两个复选框.
  • 再次单击该按钮.只prop选中了复选框.砰!

$('button').on('click', function() {
  $('#attr').attr('checked', 'checked')
  $('#prop').prop('checked', true)
})
Run Code Online (Sandbox Code Playgroud)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label>attr <input id="attr" type="checkbox"></label>
<label>prop <input id="prop" type="checkbox"></label>
<button type="button">Set checked attr and prop.</button>
Run Code Online (Sandbox Code Playgroud)

对于像disabledon 这样的属性button,添加或删除content属性disabled="disabled"总是切换属性(在HTML5中称为IDL属性),因为http://www.w3.org/TR/html5/forms.html#attr-fe-disabled说:

禁用的IDL属性必须反映已禁用的内容属性.

所以你可能会侥幸逃脱它,虽然它很难看,因为它不需要修改HTML.

对于像checked="checked"on 这样的其他属性input type="checkbox",事情会中断,因为一旦你点击它就会变脏,然后添加或删除checked="checked"内容属性就不再切换检查.

这就是为什么你应该主要使用.prop它,因为它直接影响有效属性,而不是依赖于修改HTML的复杂副作用.


Arn*_* F. 32

一切都在文档中:

在特定情况下,属性和属性之间的差异可能很重要.在jQuery 1.6之前,.attr()方法有时在检索某些属性时会考虑属性值,这可能会导致行为不一致.从jQuery 1.6开始,.prop()方法提供了一种显式检索属性值的方法,而.attr()则检索属性.

所以使用道具!

  • 我似乎记得.` $ .attr()`在大部分时间里使用它来检索属性,而不是"有时".由它引起的混乱今天仍然是共鸣.遗憾的是,我在查找关于HTML属性和DOM属性的*权威*读取时遇到了很多麻烦,所以我可能会在这里写一个答案. (6认同)
  • @ Arnaud-f不对.使用attr('checked')检查复选框的1.6之前的所有代码现在都将被破坏. (3认同)
  • @Matt麦克唐纳:什么样的"......找不到关于HTML属性和DOM属性的*确定*读取......"你的意思是什么?属性(反映的和其他的)在[DOM2 HTML规范](http://www.w3.org/TR/DOM-Level-2-HTML/)中描述; 您可能还需要参考[DOM2](http://www.w3.org/TR/DOM-Level-2-Core/)和[DOM3](http://www.w3.org/TR/ DOM-Level-3-Core /)规范. (3认同)
  • 所以这意味着当我切换到1.6时,很多事情会破裂? (2认同)

lak*_*are 27

属性在HTML 文本文档/文件中(==想象这是解析html标记的结果),而
属性在HTML DOM树中(==基本上是JS意义上某个对象的实际属性).

重要的是,其中许多是同步的(如果更新class属性,classhtml中的属性也将更新;否则).但是某些属性可能会同步到意外的属性 - 例如,属性 checked对应于属性 defaultChecked,因此

  • 手动选中复选框将更改.prop('checked')值,但不会更改.attr('checked').prop('defaultChecked')
  • 设置$('#input').prop('defaultChecked', true)也会改变.attr('checked'),但这在元素上是不可见的.

经验法则是:.prop()方法应该用于布尔属性/属性以及html中不存在的属性(例如window.location).所有其他属性(您可以在html中看到的属性)可以并且应该继续使用该.attr() 方法进行操作.(http://blog.jquery.com/2011/05/10/jquery-1-6-1-rc-1-released/)

这是一个表格,显示.prop()首选的地方(尽管.attr()仍然可以使用).

具有首选用途的表格


你为什么有时想使用.prop()代替.attr(),后者是官方建议的?

  1. .prop()可以返回任何类型 - 字符串,整数,布尔值; 而.attr()总是返回一个字符串.
  2. .prop()据说比它快约2.5倍.attr().


Kgn*_*web 18

.attr():

  • 获取匹配元素集中第一个元素的属性值.
  • 为您提供元素的值,因为它是在页面加载的html中定义的

.prop():

  • 获取匹配元素集中第一个元素的属性值.
  • 提供通过javascript/jquery修改的元素的更新值


nao*_*aor 13

通常你会想要使用属性.仅将属性用于:

  1. 获取自定义HTML属性(因为它未与DOM属性同步).
  2. 获取不与DOM属性同步的HTML属性,例如获取标准HTML属性的"原始值",例如 <input value="abc">.


NkS*_*NkS 7

attributes - > HTML

properties - > DOM

  • 我知道你想说什么,但HTML是一种标记语言,DOM是一种用HTML创建的表示.DOMElement同时具有_attributes_和_properties_. (8认同)

Got*_*urz 6

在jQuery 1.6之前,该attr()方法有时在检索属性时考虑属性值,这会导致相当不一致的行为.

prop()方法的引入提供了一种显式检索属性值的方法,同时.attr()检索属性.

文件:

jQuery.attr() 获取匹配元素集中第一个元素的属性值.

jQuery.prop() 获取匹配元素集中第一个元素的属性值.


Bob*_*ein 6

有一件事.attr()可以做.prop()而不能做:影响 CSS 选择器

这是我在其他答案中没有看到的问题。

CSS 选择器[name=value]

  • 将回应.attr('name', 'value')
  • 但并不总是.prop('name', 'value')

.prop()仅影响少数属性选择器

.attr()影响所有属性选择器