.prop()vs .attr()

时间:2011-05-03 19:33:28

标签: javascript jquery dom attr prop

因此jQuery 1.6具有新功能prop()

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

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

如果我必须切换到使用prop(),那么如果我切换到1.6,所有旧的attr()来电都会中断吗?

更新

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);
});
<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>

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

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

19 个答案:

答案 0 :(得分:1821)

2012年11月1日更新

我的原始答案特别适用于jQuery 1.6。我的建议保持不变,但jQuery 1.6.1略有改变:面对预测的一堆破碎的网站,jQuery团队reverted attr() to something close to (but not exactly the same as) its old behaviour for Boolean attributes。 John Resig也blogged about it。我可以看到他们遇到的困难,但仍然不同意他更喜欢attr()的建议。

原始回答

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

我将总结主要问题:

  • 您通常需要prop()而不是attr()
  • 在大多数情况下,prop()执行attr()过去所做的事情。在代码中用attr()替换prop()的来电通常会有效。
  • 属性通常比属性更容易处理。属性值可以只是一个字符串,而属性可以是任何类型。例如,checked属性是布尔值,style属性是每个样式具有单独属性的对象,size属性是数字。
  • 如果属性和具有相同名称的属性都存在,通常更新一个将更新另一个,但输入的某些属性不是这种情况,例如valuechecked:对于这些属性,属性始终表示当前状态,而属性(旧版本的IE除外)对应于输入的默认值/检查(反映在defaultValue / defaultChecked属性中)。
  • 此更改删除了一些在属性和属性前面停留的魔法jQuery层,这意味着jQuery开发人员必须了解属性和属性之间的差异。这是件好事。

如果你是一个jQuery开发人员并且对整个业务的属性和属性感到困惑,你需要退后一步并学习一点,因为jQuery不再那么努力保护你免受这些东西的影响。对于关于该主题的权威但有点干的词,有规格:DOM4HTML DOMDOM Level 2DOM Level 3。 Mozilla的DOM文档适用于大多数现代浏览器,并且比规范更易于阅读,因此您可能会发现他们的DOM reference很有帮助。有section on element properties

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

<input id="cb" type="checkbox" checked>
<input id="cb" type="checkbox" checked="checked">

那么,你怎么知道是否用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/

答案 1 :(得分:645)

我想Tim said it quite well,但让我们退后一步:

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

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

<a href='foo.html' class='test one' name='fooAnchor' id='fooAnchor'>Hi</a>

一些无偿的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"

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

link对象是真实的,您可以看到在它上面访问属性和访问属性之间存在真正的区别。 / p>

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

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

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

自定义属性包括,例如,您可能放置在元素上的任何data-xyz属性,以便为您的代码提供元数据(现在,只要您坚持使用{{1 }} 字首)。 (jQuery的最新版本允许您通过data-函数访问data-xyz元素,但该函数只是data属性的访问者[它同时执行越来越少];除非你真的需要它的功能,否则我会使用data-xyz函数与attr属性进行交互。)

data-xyz函数曾经有一些复杂的逻辑来获得他们想要的东西,而不是字面上得到属性。它混淆了这些概念。移至attrprop意味着将它们解除混淆。简要地说,在v1.6.0中jQuery在这方面走得太远了,但是was quickly added backattr的功能处理了人们在技术上应该使用attr时使用attr的常见情况。

答案 2 :(得分:244)

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

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

HTML属性

语法:

<body onload="foo()">

<强>目的: 允许标记为事件,渲染和其他目的提供与之关联的数据。

<强>可视化: HTML Attributes class属性显示在正文中。可通过以下代码访问:

var attr;
attr = document.body.getAttribute("class");
//IE 8 Quirks and below
attr = document.body.getAttribute("className");

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

DOM属性

语法:

document.body.onload = foo;

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

<强>可视化: DOM Properties

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

文档

实施例

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

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

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

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

-Matt

答案 3 :(得分:239)

属性在DOM中;一个属性在HTML中被解析为DOM。

更多细节

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

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

示例:当您的代码没有class属性时,DOM属性className确实存在,并且字符串值为空。

修改

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

答案 4 :(得分:136)

HTML属性和DOM对象之间的区别只会导致混淆。对于那些对DOM元素感到满意的人来说,this.src this.value this.checked等本地属性,.prop是对家庭的热烈欢迎。对于其他人来说,这只是一层混乱。让我们清楚一点。

查看.attr.prop之间差异的最简单方法是以下示例:

<input blah="hello">
  1. $('input').attr('blah') :按预期返回'hello'。这里没有意外。
  2. $('input').prop('blah') :返回undefined - 因为它正在尝试执行[HTMLInputElement].blah - 并且该DOM对象上不存在此类属性。它仅作为该元素的属性存在于范围内,即[HTMLInputElement].getAttribute('blah')
  3. 现在我们改变一些事情:

    $('input').attr('blah', 'apple');
    $('input').prop('blah', 'pear');
    
    1. $('input').attr('blah') :返回'apple'嗯?为什么不在这个元素上设置“梨”。因为属性是在输入属性上更改的,而不是DOM输入元素本身 - 它们基本上彼此独立地工作。
    2. $('input').prop('blah') :返回'pear'
    3. 出于上述原因,你真正需要注意的是不要在整个应用程序中混用这些属性用于同一属性

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


      .attr vs .prop

      第1轮:风格

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

      第2轮:值

      <input value="hello" type="text"/>   
      
      $('input').prop('value', 'i changed the value');
      
      • .attr('value') - 返回'hello' *
      • .prop('value') - 返回'i changed the value'

      *注意:因此jQuery有.val()方法,内部等同于.prop('value')

答案 5 :(得分:50)

<强> TL; DR

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

属性是输入元素的当前状态。 属性是默认值。

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

答案 6 :(得分:35)

脏检查

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

尝试一下:

  • 点击按钮。两个复选框都已经过检查。
  • 取消选中这两个复选框。
  • 再次点击该按钮。仅检查了prop复选框。 BANG!

$('button').on('click', function() {
  $('#attr').attr('checked', 'checked')
  $('#prop').prop('checked', true)
})
<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>

对于disabledbutton等某些属性,添加或删除内容属性disabled="disabled"始终会切换属性(在HTML5中称为IDL属性),因为http://www.w3.org/TR/html5/forms.html#attr-fe-disabled说:< / p>

  

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

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

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

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

答案 7 :(得分:32)

全部在the doc

  

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

所以使用prop!

答案 8 :(得分:26)

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

重要的是,其中许多是同步的(如果更新class属性,html中的class属性也将更新;否则)。 某些属性可能会同步到意外的属性 - 例如,属性 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())。

table with preferred usage

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

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

答案 9 :(得分:18)

.attr()

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

.prop()

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

答案 10 :(得分:13)

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

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

答案 11 :(得分:7)

attributes - &gt; HTML

properties - &gt; DOM

答案 12 :(得分:6)

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

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

文件:

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

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

答案 13 :(得分:2)

轻轻提醒您使用prop(),例如:

if ($("#checkbox1").prop('checked')) {
    isDelete = 1;
} else {
    isDelete = 0;
}

上面的函数用于检查checkbox1是否被选中,如果选中:return 1;如果不是:返回0.函数prop()在这里用作GET函数。

if ($("#checkbox1").prop('checked', true)) {
    isDelete = 1;
} else {
    isDelete = 0;
}

上面的函数用于设置要检查的checkbox1并且总是返回1.现在函数prop()用作SET函数。

不要搞砸。

P / S:当我检查图像 src 属性时。如果 src 为空, prop 会返回页面的当前网址(错误), attr 会返回空string(右)。

答案 14 :(得分:2)

jQuery 1.6引入了.prop()函数并分离了DOM属性和属性,它引发了很多关于.attr和.prop函数之间差异的问题。

见下面的例子:

实施例:1)

<input id="demo" type="text" dbvalue="Kansagara" />

$("#demo").attr("dbvalue");   // returns Kansagara
$("#demo").prop("dbvalue");   // returns undefined

.prop()只返回HTML DOM属性的值,它没有返回自定义属性的值,而.attr()也返回如上所示的自定义属性值。

实施例:2)

<input id="demo" type="text" value="Kansagara" />

现在,我在文本框中将'Kansagara'文本更改为'Hitesh'。

$("#demo").attr("value");   // returns Kansagara
$("#demo").prop("value");   // returns Hitesh

现在你已经知道这意味着什么。只更改了元素的属性,因为它在DOM中是动态的。但元素的属性是HTML文本,无法更改。从广义上讲,属性总是表示当前状态,而属性(IE的旧版本除外)表示初始状态或者是html属性,因为它们是严格定义的。该属性不会告诉您当前的状态。

表示复选框(jquery 1.6 +)

<input id="check1" checked="checked" type="checkbox" />

.attr('checked') //returns  checked
.prop('checked') //returns  true
.is(':checked') //returns true

prop方法返回checked,selected,disabled,readOnly..etc的布尔值,而attr返回已定义的字符串。因此,您可以在if条件下直接使用.prop('checked')。

.attr()在内部调用.prop(),所以.attr()方法比直接通过.prop()访问它们要慢一些。

对于jQuery 1.6+,将主要使用prop,因为它比attr简单且宽泛。在大多数旧项目中,attr用于获取元素的当前状态信息。但是现在道具已经接受了这项工作,而attr将被替换为道具。

希望,它有所帮助。

答案 15 :(得分:0)

  

1)属性在DOM中; HTML中的属性是   解析为DOM。

     

2)$(elem).attr(&#34;已检查&#34;)(1.6.1 +)&#34;已检查&#34; (String)Will   用复选框状态更改

     

3)$(elem).attr(&#34; checked&#34;)(pre-1.6)true(布尔值)已更改   使用复选框状态

  • 我们通常希望使用DOM对象而不是自定义属性 比如GridItems

  • 访问data-img, data-xyz值和checkbox时也存在一些差异 hrefattr()随着DOM输出的变化而变化 prop()的完整链接prop()origin值的复选框 Boolean

  • 我们只能使用(pre-1.6)访问DOM元素,然后才能 prop

&#13;
&#13;
undefined
&#13;
&#13;
&#13;

答案 16 :(得分:0)

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

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

CSS选择器[name=value]

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

.prop()仅影响几个属性选择器

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

答案 17 :(得分:0)

prop()与attr()相比,还有更多注意事项:

    应该检索并使用.prop()方法设置
  • selectedIndex,tagName,nodeName,nodeType,ownerDocument,defaultChecked和defaultSelected..etc。这些没有相应的属性,而仅仅是属性。

  • 对于输入类型复选框

       .attr('checked') //returns  checked
       .prop('checked') //returns  true
       .is(':checked') //returns true
    
  • prop方法返回布尔值,表示已选中,已选中,已禁用, readOnly..etc,而attr返回定义的字符串。因此,您可以直接 在条件中使用.prop('checked')。

  • .attr()内部调用.prop(),因此.attr()方法会稍微 比通过.prop()直接访问它们要慢。

答案 18 :(得分:-3)

如果代码以这种方式编写,那么Gary Hole的答案与解决问题非常相关

obj.prop("style","border:1px red solid;")

由于prop函数返回CSSStyleDeclaration对象,上面的代码在某些浏览器中无法正常工作(在我的情况下使用IE8 with Chrome Frame Plugin进行测试)。

因此将其改为以下代码

obj.prop("style").cssText = "border:1px red solid;"

解决了这个问题。