.prop()vs .attr()

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

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

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

如果我必须切换到使用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); }); 
 <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/ )

控制台以stringformslogginggetAttribute ,以stringformsloggingattr ,但将prop作为CSSStyleDeclaration ,为什么? 而且这对未来的编码有什么影响?

2012年11月1日更新

我原来的答案特别适用于jQuery 1.6。 我的build议仍然是一样的,但jQuery 1.6.1稍微改变了一些事情:面对预测的一堆破损的网站,jQuery团队将attr()恢复到了与布尔属性的旧行为接近(但不完全相同) 。 约翰·雷西格也对此进行了博客 。 我可以看到他们遇到的困难,但仍然不同意使用attr()的build议。

原始答案

如果你只使用jQuery而不是直接使用DOM,这可能是一个令人困惑的变化,尽pipe这在概念上绝对是一个改进。 对于那些使用jQuery的站点来说,这样做并不是那么好,但是由于这个变化,这个站点会崩溃。

我将总结一下主要问题:

  • 你通常需要prop()而不是attr()
  • 在大多数情况下, prop()attr()用来做的事情。 用代码中的prop()replace对attr()调用通常是可行的。
  • 属性通常比属性更容易处理。 属性值可能只是一个string,而属性可以是任何types。 例如, checked属性是一个布尔值, style属性是每个样式具有单独属性的对象, size属性是一个数字。
  • 在存在同名的属性和属性的情况下,通常更新一个会更新另一个属性,但是对于某些input属性(例如valuechecked ,情况并非如此:对于这些属性,属性总是表示当前状态而这个属性(除了旧版本的IE)对应于input的缺省值/检查(反映在defaultValue / defaultChecked属性中)。
  • 这个变化消除了一些被属性和属性粘住的魔法jQuery层,这意味着jQuery开发者将不得不学习一些属性和属性之间的区别。 这是一件好事。

如果你是一个jQuery开发人员,并且被整个业务混淆了属性和属性,那么你需要退后一步,稍微了解一下它,因为jQuery不再试图用这种方式来保护你。 关于这个主题的权威性,但有点干燥的话,还有规范: DOM4 , HTML DOM , DOM Level 2 , DOM Level 3 。 Mozilla的DOM文档适用于大多数现代浏览器,比规范更容易阅读,因此您可能会发现他们的DOM参考很有帮助。 有一个关于元素属性的部分 。

作为属性如何处理比属性更简单的一个例子,考虑一个最初被选中的checkbox。 这里有两个有效的HTML可以做到这一点:

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

那么,你怎么知道这个checkbox是否被jQuery检查过? 看看堆栈溢出,你会经常发现以下build议:

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

这实际上是世界上最简单的事情,使用checked布尔属性,自1995年以来,在每个主要的脚本浏览器已经存在和工作完美:

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

该属性还使检查或取消选中checkbox琐碎:

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

在jQuery 1.6中,这明确地成为

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

使用checked属性来为checkbox编写脚本的想法是无用的和不必要的。 该属性是你所需要的。

  • 不清楚检查或取消选中checkbox的正确方法是使用checked属性
  • 该属性值反映了默认值而不是当前的可见状态(除了在IE的一些旧版本,因此使事情变得更加困难)。 该属性不会告诉你关于页面上的checkbox是否被选中。 请参阅http://jsfiddle.net/VktA6/49/

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

一个DOM元素是一个对象,是一个内存中的东西。 像OOP中的大多数对象一样,它具有属性 。 它还分别具有在元素上定义的属性的映射(通常来自浏览器读取以创build元素的标记)。 一些元素的属性从具有相同或相似名称的属性中获取它们的初始值( value从“value”属性获得它的初始值; href从“href”属性获得它的初始值,但它不是完全相同的值; className属性中的className )。 其他属性以其他方式获取其初始值:例如, parentNode属性根据其父元素的值获取其值; 一个元素总是有一个style属性,不pipe它是否有“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”|
 | 名称:“fooAnchor”|
 |  id:“fooAnchor”|
 |  className:“test one”|
 | 属性:|
 |  href:“foo.html”|
 | 名称:“fooAnchor”|
 |  id:“fooAnchor”|
 | 类:“testing一”|
 + ------------------------------------------- +

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

现在,虽然它们是截然不同的,但是所有这些都是从头开始devise的,而不是从头开始devise的,所以如果你设置了属性的话,许多属性会回写它们来源的属性。 但并非所有人都这么做,正如你从上面的介绍中看到的那样,映射并不总是“直接传递价值”,有时还有解释。

当我谈论属性是一个对象的属性时,我不是抽象的。 这里有一些非jQuery代码:

 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

这些规格有优秀的指标,我build议保持与他们方便的链接; 我一直使用它们。

自定义属性包括,例如,你可能会放在元素上的任何data-xyz属性,以便为你的代码提供元数据(现在只要你坚持data-前缀,那么它就是HTML5的有效性)。 (最近的jQuery版本让你可以通过data函数访问data-xyz元素,但是这个函数不仅仅是data-xyz属性的一个访问器[它不仅仅是这么做];除非你确实需要它的特性, '使用attr函数与data-xyz属性进行交互。

attr函数过去有一些令人费解的逻辑来获取他们想要的东西,而不是逐字地获取属性。 它把概念混为一谈。 转移到propattr是为了去混合他们。 简单地说,在v1.6.0中,jQuery在这方面做得太过分了,但是function被快速添加回 attr来处理人们在技术上使用attr时常常使用attr情况。

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

属性以stringforms返回,并且可能从浏览器到浏览器不一致。 但是,在某些情况下,它们可能至关重要。 如上所示,IE 8 Quirks Mode(及以下)期望get / set / removeAttribute中DOM属性的名称,而不是属性名称。 这是为什么重要的是要知道差异的原因之一。

DOM属性

句法:

document.body.onload = foo;

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

可视化: DOM属性

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

文档

  • JavaScript:David Flanagan的权威指南
  • HTML属性,Mozilla开发人员中心
  • DOM元素属性,Mozilla开发人员中心

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

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

在早期版本的jQuery中,这返回一个空string。 在1.6中,它返回适当的值foo

没有浏览任何一个函数的新代码,我可以自信地说,混淆更多的是HTML属性和DOM属性之间的区别,而不是代码本身。 希望这能为你解决一些问题。

-Matt

属性在DOM中; HTML中的一个属性被分析到DOM中。

更多细节

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

示例:更改标签的class属性将改变DOM中该标签的className属性。 如果你没有标签的属性,你仍然有相应的DOM属性,一个空的或默认值。

例如:当您的标签没有class属性时,DOM属性className确实存在一个空的string值。

编辑

如果你改变一个,另一个将被控制器改变,反之亦然。 这个控制器不在jQuery中,而是在浏览器的本地代码中。

这只是HTML属性和DOM对象之间的区别造成的混淆。 对于那些在DOM元素本身的属性(如this.src this.value this.checked等等)上.prop来说, .prop是一个非常热烈的欢迎。 对于其他人来说,这只是一个混乱的层面。 我们来清楚一点。

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

 <input blah="hello"> 
  1. $('input').attr('blah') :按照预期返回'hello' 。 这里没有什么惊喜。
  2. $('input').prop('blah') :返回undefined – 因为它试图执行[HTMLInputElement].blah – 并且该DOM对象上不存在这样的属性。 它只存在于作为该元素的属性的作用域中,即[HTMLInputElement].getAttribute('blah')

现在我们改变几件事情:

 $('input').attr('blah', 'apple'); $('input').prop('blah', 'pear'); 
  1. $('input').attr('blah') :返回'apple' apple'eh? 为什么不“梨”,因为这是最后的那个元素。 由于该属性在input属性上发生了变化,而不是DOMinput元素本身 – 它们基本上几乎独立工作。
  2. $('input').prop('blah') :返回'pear'

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

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


.attr vs .prop

第一轮:风格

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

第二轮:价值

 <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')

TL; DR

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

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

属性可以包含不同types的东西。 一个属性只能包含string

肮脏的检查是一个例子,其中的差异是可观察的

要看到它,请运行以下代码片段:

  • 点击button。 这两个checkbox被检查。
  • 取消勾选这两个checkbox。
  • 再次点击button。 只有propcheckbox被检查。 砰!
 $('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> 

全部在文档中:

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

所以使用道具!

属性是在你的HTML 文本文件/文件 (==想象这是你的HTML标记parsing的结果),而
属性在HTML DOM树 (==基本上是JS意义上的某个对象的实际属性)。

重要的是,他们中的许多人同步(如果你更新class属性,HTML中的class属性也将被更新,否则)。 但是一些属性可能同步到意想不到的属性 – 例如, checked 属性对应于属性 defaultChecked ,所以

  • 手动检查checkbox将改变.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()可以返回任何types – string,整数,布尔值; 而.attr()总是返回一个string。
  2. .prop()据说比.attr()快大约2.5倍。

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

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

.attr(): –

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

.prop(): –

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

attributes – > HTML

properties – > DOM

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

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

文件:

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

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

轻轻提醒一下使用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; } 

Function above is used to set checkbox1 to be checked and ALWAYS return 1. Now function prop() used as a SET function.

Don't mess up.

P/S: When I'm checking Image src property. If the src is empty, prop return the current url of the page (wrong), and attr return empty string (right).

1) A property is in the DOM; HTML中的一个属性被分析到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

  • Mostly we want to use for DOM object rather then custom attribute like data-img, data-xyz .

  • Also some of difference when accessing checkbox value and href with attr() and prop() as thing change with DOM output with prop() as full link from origin and Boolean value for checkbox (pre-1.6)

  • We can only access DOM elements with prop other then it gives undefined

 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.0/jquery.min.js"></script> <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>prop demo</title> <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> <script> $("input").change(function() { var $input = $(this); $("p").html( ".attr( \"checked\" ): <b>" + $input.attr("checked") + "</b><br>" + ".prop( \"checked\" ): <b>" + $input.prop("checked") + "</b><br>" + ".is( \":checked\" ): <b>" + $input.is(":checked")) + "</b>"; }).change(); </script> </body> </html> 

Gary Hole answer is very relevant to solve the problem if the code is written in such way

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

Since the prop function return CSSStyleDeclaration object, above code will not working properly in some browser(tested with IE8 with Chrome Frame Plugin in my case).

Thus changing it into following code

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

解决问题。