关于javascript:.prop()vs .attr()

.prop() vs .attr()

所以jquery 1.6有了新的函数prop()

1
2
3
4
5
6
7
8
$(selector).click(function(){
    //instead of:
    this.getAttribute('style');
    //do i use:
    $(this).prop('style');
    //or:
    $(this).attr('style');
})

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

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

更新

1
2
3
4
5
6
7
8
9
10
11
12
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);
});
1
2
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.0/jquery.min.js">
test

(另请参见此小提琴:http://jsfiddle.net/maniator/jpuf2/)

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


更新时间:2012年11月1日

我的原始答案专门适用于jquery 1.6。我的建议保持不变,但jquery 1.6.1稍微改变了一些:面对预测到的一堆被破坏的网站,jquery团队将attr()恢复为接近(但不完全相同)其布尔属性的旧行为。约翰·雷西格也在博客中提到了这一点。我可以看出他们所处的困难,但我仍然不同意他的建议,即选择attr()

原始答案

如果您只使用过jquery而没有直接使用DOM,那么这可能是一个令人困惑的更改,尽管它在概念上确实是一个改进。不过,对于使用jquery的无数网站来说,这并不是很好,因为这种变化会导致大量网站中断。

我将总结主要问题:

  • 你通常想要prop(),而不是attr()
  • 在大多数情况下,prop()会像attr()那样做。用代码中的prop()替换对attr()的调用通常是有效的。
  • 属性通常比属性更容易处理。属性值只能是字符串,而属性可以是任何类型。例如,checked属性是布尔值,style属性是每种样式都有单独属性的对象,size属性是数字。
  • 当属性和同名属性同时存在时,通常更新一个属性会更新另一个属性,但输入的某些属性(如valuechecked不是这样的:对于这些属性,属性总是表示当前状态,而属性(除旧版本的IE外)对应于输入的默认值/检查性(反映在defaultValue/defaultChecked属性中)。
  • 这一改变消除了一些卡在属性和属性前面的magic jquery层,这意味着jquery开发人员必须了解一些属性和属性之间的区别。这是件好事。

如果您是一个jquery开发人员,并且对整个业务中的属性和属性感到困惑,那么您需要后退一步,稍微了解一下它,因为jquery已经不再那么努力地保护您不受这些影响了。对于这个主题权威但有些枯燥的词,有一些规范:dom4、html dom、dom级别2、dom级别3。Mozilla的DOM文档对大多数现代浏览器都有效,并且比规范更容易阅读,因此您可能会发现它们的DOM引用很有用。有一个关于元素属性的部分。

作为属性比属性更容易处理的示例,请考虑最初选中的复选框。下面是两个有效的HTML文件:

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

那么,如何确定这个复选框是否被jquery选中?查看堆栈溢出,您通常会发现以下建议:

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

这实际上是世界上处理checked布尔属性最简单的方法,自1995年以来,checked布尔属性在每种主要的可脚本浏览器中都存在并运行良好:

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/。


我觉得蒂姆说得很好,但让我们退一步:

dom元素是一个对象,是内存中的一个东西。与OOP中的大多数对象一样,它也具有属性。另外,它还分别具有在元素上定义的属性映射(通常来自浏览器读取以创建元素的标记)。元素的某些属性从具有相同或相似名称的属性中获取其初始值(value从"value"属性中获取其初始值;href从"href"属性中获取其初始值,但其值并不完全相同;className从"class"属性中获取)。其他属性以其他方式获取其初始值:例如,parentNode属性根据其父元素是什么来获取其值;元素始终具有style属性,不管它是否具有"style"属性。

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

1
Hi

一些免费的ASCII艺术(并且遗漏了很多东西):

1
2
3
4
5
6
7
8
9
10
11
12
13
+???????????????????????????????????????????+
|             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代码:

1
2
3
var link = document.getElementById('fooAnchor');
alert(link.href);                 // alerts"http://example.com/foo.html"
alert(link.getAttribute("href")); // alerts"foo.html"

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

link对象是真实的,您可以看到访问它上的属性和访问属性之间有一个真正的区别。

正如蒂姆所说,绝大多数情况下,我们都想与物业合作。部分原因是它们的值(甚至名称)在浏览器中趋向于更加一致。我们通常只想在没有相关属性(自定义属性)的情况下使用属性,或者当我们知道对于该特定属性,属性和属性不是1:1(与上面的href和"href"一样)。

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

  • dom2 html(大部分已过时,请参阅html规范)
  • DOM2核心(过时)
  • DOM3核心(过时)
  • DOM4

这些规范有很好的索引,我建议您随时使用它们的链接。

例如,自定义属性将包括您可能放在元素上以向代码提供元数据的任何data-xyz属性(现在,只要您坚持使用data-前缀,HTML5就有效了)。(jquery的最新版本允许您通过data函数访问data-xyz元素,但该函数不仅仅是data-xyz属性的一个访问器[它的作用大于或小于此];除非您确实需要它的功能,否则我将使用attr函数与data-xyz属性交互。)

attr函数过去有一些复杂的逻辑来获得他们认为你想要的东西,而不是从字面上获得属性。它混淆了这些概念。移到propattr是为了消除它们之间的混淆。简言之,在v1.6.0版中,jquery在这方面做得太过分了,但很快又将功能添加回attr,以处理人们在技术上应该使用prop时使用attr的常见情况。


对于jquery来说,这种变化已经很久了。多年来,它们一直满足于一个名为attr()的函数,该函数主要检索DOM属性,而不是您期望的名称结果。attr()prop()的分离有助于缓解HTML属性和DOM属性之间的一些混淆。$.fn.prop()获取指定的dom属性,而$.fn.attr()获取指定的html属性。

为了充分理解它们的工作原理,下面是关于HTML属性和DOM属性之间区别的扩展说明:

HTML属性Syntax:

用途:允许标记具有与之关联的数据,用于事件、呈现和其他目的。

可视化:HTML Attributes类属性显示在主体上。可通过以下代码访问:

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

属性以字符串形式返回,并且在浏览器和浏览器之间可能不一致。然而,在某些情况下,它们可能是至关重要的。如上示例所示,IE8 quirks模式(及以下)要求get/set/removeattribute中的dom属性名而不是属性名。这是了解差异很重要的原因之一。

DOM属性Syntax:

document.body.onload = foo;

用途:允许访问属于元素节点的属性。这些属性与属性类似,但只能通过JavaScript访问。这是一个重要的区别,有助于澄清DOM属性的作用。请注意,属性与属性完全不同,因为此事件处理程序分配是无用的,不会接收事件(主体没有onload事件,只有onload属性)。

可视化:DOM Properties

在这里,您会注意到Firebug中"dom"选项卡下的属性列表。这些是DOM属性。你会立刻注意到其中的很多,因为你以前在不知道的情况下使用过它们。它们的值就是您将通过JavaScript接收到的值。

文档

  • javascript:最终指南作者
  • HTML属性,Mozilla开发中心
  • Dom元素属性,Mozilla开发中心

例子

html:

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

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

在没有浏览过这两个函数的新代码的情况下,我可以自信地说,这种混淆更多地与HTML属性和DOM属性之间的区别有关,而不是与代码本身有关。希望这能帮你解决一些问题。

-马特


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

进一步细节

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

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

示例:虽然标记没有class属性,但dom属性className确实存在一个空字符串值。

编辑

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


HTML属性和DOM对象之间的区别导致了混淆。对于那些对DOM元素自然属性(如this.srcthis.valuethis.checked等)感到舒适的人来说,.prop是一个非常热烈的家庭欢迎。对于其他人来说,这只是一个额外的混乱层。让我们澄清一下。

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

1
<input blah="hello">
  • $('input').attr('blah'):按预期返回'hello'。这里没有惊吓。
  • $('input').prop('blah'):返回undefined,因为它试图执行[HTMLInputElement].blah,并且该dom对象上不存在这样的属性。它只作为该元素的属性存在于作用域中,即[HTMLInputElement].getAttribute('blah')
  • 现在我们改变一些事情,比如:

    1
    2
    $('input').attr('blah', 'apple');
    $('input').prop('blah', 'pear');
  • $('input').attr('blah')返回'apple'嗯?为什么不把"梨"放在最后一个元素上呢?因为属性是在input属性上更改的,而不是dom输入元素本身——它们基本上彼此独立工作。
  • $('input').prop('blah'):返回'pear'
  • 您真正需要注意的是,由于上述原因,不要在整个应用程序中为同一属性混合使用这些属性。

    请参阅演示差异的小提琴:http://jsfiddle.net/garreh/ulqxcxc/

    .attr.prop比较:第1轮:风格

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

    第2轮:价值

    1
    2
    3
    <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')方法。


    DR

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

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

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


    肮脏的检查

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

    试一试:

    • 单击按钮。两个复选框都被选中。
    • 取消选中两个复选框。
    • 再次单击按钮。只选中了prop复选框。砰!

    1
    2
    3
    4
    $('button').on('click', function() {
      $('#attr').attr('checked', 'checked')
      $('#prop').prop('checked', true)
    })
    1
    2
    3
    4
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
    <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>

    对于button上的disabled等属性,添加或删除内容属性disabled="disabled"总是切换属性(在html5中称为idl属性),因为http://www.w3.org/tr/html5/forms.html attr fe disabled表示:

    The disabled IDL attribute must reflect the disabled content attribute.

    因此,您可能会摆脱它,虽然它是丑陋的,因为它修改HTML不需要。

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

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


    全部在文档中:

    The difference between attributes and properties can be important in specific situations. Before jQuery 1.6, the .attr() method sometimes took property values into account when retrieving some attributes, which could cause inconsistent behavior. As of jQuery 1.6, the .prop() method provides a way to explicitly retrieve property values, while .attr() retrieves attributes.

    所以使用道具!


    在你的文本属性是HTML文档/文件(= =这是你想象的结果,而parsed HTML标记)属性是在HTML DOM树(一=目前的一些基本性质,在JS对象义)。

    重要的是,许多学院都是同步的(如果你在更新class物业,classHTML属性也将被更新,和其他)。但对一些意外的性质,可能是同步的属性,如属性,属性对应于checkeddefaultChecked,这样

    • 手动检查复选框,将在.prop('checked')值变化,但不会改变.attr('checked').prop('defaultChecked')
    • 设置$('#input').prop('defaultChecked', true).attr('checked')也将变化,但是这将是不可见的在线一元。

    Rule of thumb is: .prop() method should be used for boolean attributes/properties and for properties which do not exist in html
    (such as window.location). All other attributes (ones you can see in
    the html) can and should continue to be manipulated with the .attr()
    method. (http://blog.jquery.com/2011/05/10/jquery-1-6-1-rc-1-released/)

    这是显示在表和地方的优先.prop()(虽然.attr()仍然可以被使用)。

    table with preferred usage为什么你会想使用.prop .attr()()而不是在adviced则是正式的吗?

  • .prop()可以返回任何类型的字符串,整数,布尔,在.attr()总是返回的字符串。
  • .prop()说是约2.5倍,是比.attr()更快。

  • .attr()

    • 获取属性值的第一组匹配的元素中的元素。
    • 给你的价值,这是定义的元素的HTML页面中的网络负载

    .prop()

    • 得到的价值的财产的第一个匹配的元素中的元素集。
    • 好的,这是最新的价值观的路径元素的jQuery JavaScript /改性

    通常,您需要使用属性。仅将属性用于:

  • 获取自定义HTML属性(因为它没有与DOM属性同步)。
  • 获取与dom属性不同步的html属性,例如获取标准html属性的"原始值",如.

  • attributes→HTML

    properties->礼品


    在jQuery的方法了attr()1.6,有时对客户查询的属性值的属性时,这相当不一致的行为。

    在介绍的方法提供了prop()明确检索属性值的方式,而.attr()retrieves属性。

    该文档:

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

    jQuery.prop()得到的价值的财产的第一个匹配的元素中的元素集。


    jquery 1.6引入了.prop()函数,分离了dom属性和属性,对.attr和.prop函数的区别提出了很多问题。

    见以下示例:

    例子:1)

    1
    2
    3
    4
    <input id="demo" type="text" dbvalue="Kansagara" />

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

    .prop()只返回html dom属性的值,它不返回自定义属性的值,.attr()也返回自定义属性值,如上图所示。

    例子:2)

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

    现在,我在文本框中将文本"kansagara"改为"hitesh"。

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

    现在你知道它的意思了。只有元素的属性被更改,因为它在dom和dynamic中。但元素的属性是HTML文本,不能更改。从广义上讲,属性总是表示当前状态,而属性(旧版IE除外)表示初始状态,或者是严格定义的HTML属性。该属性不会告诉您有关当前状态的任何信息。

    对于复选框(jquery 1.6+)

    1
    2
    3
    4
    5
    <input id="check1" checked="checked" type="checkbox" />

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

    prop方法为checked、selected、disabled、readonly等返回布尔值,而attr返回定义的字符串。因此,您可以直接在if条件中使用.prop("checked")。

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

    对于jquery 1.6+,将主要使用prop,因为它比attr简单且更宽。在大多数老项目中,ATTR用于获取元素的当前状态信息。但现在道具已经接受了这个任务,ATTR将被道具取代。

    希望,它有帮助。


    轻轻地提醒我们:利用prop(),例子

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

    这些功能是用来检查如果checkbox1检查或不检查,如果是,返回1;如果不返回0。在这里使用的道具()函数获得的功能。

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

    这些功能是用来设置checkbox1被检查和总是返回1。现在使用的道具()函数的功能集。

    Don’t混乱起来。

    P / S:当我检查图像的src属性。如果src是空,返回当前页面的URL的(错误的)和属性(右)返回空字符串。


    1) A property is in the DOM; an attribute is in the HTML that is
    parsed into the DOM.

    2) $( elem ).attr("checked" ) (1.6.1+) "checked" (String) Will
    change with checkbox state

    3) $( elem ).attr("checked" ) (pre-1.6) true (Boolean) Changed
    with checkbox state

    • 我们要使用的是定制的,而当时的DOM对象的属性data-img, data-xyz样。

    • 也有些时候checkboxhref访问值和差分一个具有attr()prop()的变化与输出与礼品的链接和来自全prop()originBoolean值的复选框(pre-1.6)

    • 我们可以只读访问DOM元素,然后使它与其他undefinedprop

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.0/jquery.min.js">
    <!doctype html>
    <html lang="en">

    <head>
      <meta charset="utf-8">
      prop demo
      <style>
        p {
          margin: 20px 0 0;
        }
        b {
          color: blue;
        }
      </style>

    </head>

    <body>

      <input id="check1" type="checkbox" checked="checked">
      <label for="check1">Check me</label>
      <p>

    </p>

     
        $("input").change(function() {
          var $input = $(this);
          $("p").html(
           ".attr( "checked" ):" + $input.attr("checked") +"" +
           ".prop( "checked" ):" + $input.prop("checked") +"" +
           ".is( ":checked" ):" + $input.is(":checked")) +"";
        }).change();
     

    </body>

    </html>


    加里回答之间的孔是非常相关的问题,如果是在这样的方式编写的代码

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

    由于函数返回的对象上的CSSStyleDeclaration道具,将不恰当的一些代码在浏览器的工作(在我的测试案例与IE8 with Chrome Frame Plugin)。

    因此,下面的代码将改变它

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

    解决该问题。