.prop () vs .attr ()

2301

Portanto, o jQuery 1.6 tem a nova função prop().

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

ou, nesse caso, eles fazem a mesma coisa?

E se eu não tem que passar a usar prop(), todas as antigas attr()chamadas vai quebrar se eu mudar para 1.6?

ATUALIZAR

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>

(veja também este violino: http://jsfiddle.net/maniator/JpUF2/ )

O console registra getAttributecomo uma sequência e attrcomo uma sequência, mas propcomo como CSSStyleDeclaration, por quê? E como isso afeta minha codificação no futuro?

Naftali tcp Neal
fonte
17
Isso será de interesse definitivo: books.google.ca/…
28
@ Neal, é porque essa mudança transcende o jQuery. A diferença entre atributos HTML e propriedades DOM é enorme.
7
Fico triste em ver o jQuery reverter as alterações. Eles estão indo na direção errada.
4
@Neal. Sim, e isso apenas complica ainda mais o problema, em vez de separar os dois métodos.
6
@BritishDeveloper, a resposta é mais complicada do que simplesmente dizer sempre use x ou y, porque depende do que você pretende obter. Você deseja o atributo ou deseja a propriedade? São duas coisas muito diferentes.
Kevin B

Respostas:

1876

Atualização 1 de novembro de 2012

Minha resposta original se aplica especificamente ao jQuery 1.6. Meu conselho permanece o mesmo, mas o jQuery 1.6.1 mudou um pouco as coisas: diante da pilha prevista de sites quebrados, a equipe do jQuery voltou attr()a algo próximo (mas não exatamente o mesmo) do antigo comportamento dos atributos booleanos . John Resig também escreveu um blog sobre isso . Eu posso ver a dificuldade em que eles estavam, mas ainda discordo de sua recomendação de preferir attr().

Resposta original

Se você já usou o jQuery e não o DOM diretamente, isso pode ser uma mudança confusa, embora seja definitivamente uma melhoria conceitual. Não é tão bom para os bazilhões de sites que usam jQuery que serão interrompidos como resultado dessa alteração.

Vou resumir os principais problemas:

  • Você geralmente quer prop()e não attr().
  • Na maioria dos casos, prop()faz o que attr()costumava fazer. Substituir as chamadas attr()por prop()no seu código geralmente funcionará.
  • Geralmente, as propriedades são mais simples de lidar do que os atributos. Um valor de atributo pode ser apenas uma sequência, enquanto uma propriedade pode ser de qualquer tipo. Por exemplo, a checkedpropriedade é um booleano, a stylepropriedade é um objeto com propriedades individuais para cada estilo, a sizepropriedade é um número.
  • Onde existe uma propriedade e um atributo com o mesmo nome, geralmente atualizar um atualizará o outro, mas esse não é o caso de determinados atributos de entradas, como valuee checked: para esses atributos, a propriedade sempre representa o estado atual enquanto o O atributo (exceto nas versões antigas do IE) corresponde ao valor / verificação padrão da entrada (refletida na propriedade defaultValue/ defaultChecked).
  • Essa alteração remove parte da camada do jQuery mágico preso na frente de atributos e propriedades, o que significa que os desenvolvedores do jQuery terão que aprender um pouco sobre a diferença entre propriedades e atributos. Isto é uma coisa boa.

Se você é um desenvolvedor de jQuery e está confuso com toda essa empresa sobre propriedades e atributos, precisa dar um passo atrás e aprender um pouco sobre isso, pois o jQuery não está mais tentando se proteger dessas coisas. Para a palavra autorizada, mas um pouco seca sobre o assunto, há as especificações: DOM4 , HTML DOM , DOM Nível 2 , DOM Nível 3 . A documentação do DOM do Mozilla é válida para a maioria dos navegadores modernos e é mais fácil de ler do que as especificações, portanto, você pode achar útil a referência do DOM . Há uma seção sobre propriedades do elemento .

Como um exemplo de como as propriedades são mais simples de lidar do que os atributos, considere uma caixa de seleção inicialmente marcada. Aqui estão duas partes possíveis de HTML válido para fazer isso:

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

Então, como você descobre se a caixa de seleção está marcada com jQuery? Observe o Stack Overflow e, normalmente, você encontrará as seguintes sugestões:

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

Essa é realmente a coisa mais simples do mundo a ver com a checkedpropriedade booleana, que existe e funciona perfeitamente em todos os principais navegadores de scripts desde 1995:

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

A propriedade também torna a seleção ou desmarcação da caixa de seleção trivial:

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

No jQuery 1.6, isso se torna inequivocamente

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

A idéia de usar o checkedatributo para criar scripts para uma caixa de seleção é inútil e desnecessária. A propriedade é o que você precisa.

  • Não é óbvio qual a maneira correta de marcar ou desmarcar a caixa de seleção está usando o checkedatributo
  • O valor do atributo reflete o padrão, e não o estado visível atual (exceto em algumas versões mais antigas do IE, tornando as coisas ainda mais difíceis). O atributo não informa nada sobre se a caixa de seleção na página está marcada. Veja http://jsfiddle.net/VktA6/49/ .
Tim Down
fonte
2
@TJCrowder, então quais?
Naftali aka Neal
9
@Neal: Se você quer saber o que elementos propriedades DOM tem e como atributos podem propagar seus valores, manter estes links para mão: O DOM2 especificação HTML , o DOM2 spec, e DOM3 spec. Os índices em cada caso são excelentes e o vinculam diretamente a uma descrição completa da propriedade, de onde vem seu valor etc.
TJ Crowder
4
@ Neal: Re o que o torna diferente: A fonte e a natureza das informações. Veja o valueexemplo de Tim , por exemplo. Uma função chamada attrque recupera a propriedade value em vez do atributo "value" não faz muito sentido (e pode ser diferente). No futuro, attrfazer atributos e propfazer propriedades será mais claro, embora a transição seja dolorosa para alguns. Não leve a mal, não há nada como voltar atrás e ler as especificações para ter uma idéia de quais são as propriedades.
TJ Crowder
54
@ Neal: Um elemento DOM é um objeto. Propriedades são propriedades desse objeto, como qualquer outro objeto de programação. Alguns desses adereços obtêm seus valores iniciais dos atributos na marcação, que também são armazenados no objeto DOM em um mapa separado de atributos. Na maioria dos casos, gravar em um suporte apenas altera o suporte, embora, infelizmente, existam alguns objetos que escrevem alguma alteração no atributo subjacente ( valuepor exemplo), mas vamos tentar ignorá-lo. 99% do tempo, você deseja trabalhar com adereços. Se você precisar trabalhar com um atributo real, provavelmente saberá disso.
TJ Crowder
4
@ Tim: "Alterar a valuepropriedade de uma entrada não altera seu valueatributo nos navegadores modernos" Eu não achei que sim, e foi por isso que comecei a usá-la como exemplo, mas quando comecei a codificar o exemplo, se não foi atualizado no Chrome, Firefox, Opera, IE ... - jsbin.com/ahire4 Acontece que é porque eu estava usando um input[type="button"]para o meu experimento. Ele não atualiza o atributo em um input[type="text"]- jsbin.com/ahire4/2 Falar sobre complicado !! Não apenas o elemento, mas o tipo dela ...
TJ Crowder
664

Acho que o Tim falou muito bem , mas vamos voltar atrás:

Um elemento DOM é um objeto, uma coisa na memória. Como a maioria dos objetos no OOP, ele possui propriedades . Além disso, também possui um mapa dos atributos definidos no elemento (geralmente provenientes da marcação que o navegador leu para criar o elemento). Algumas das propriedades do elemento obtêm sua inicial valores de atributos com os mesmos nomes ou nomes semelhantes ( valueobtém seu valor inicial do atributo "value"; hrefobtém seu valor inicial do atributo "href", mas não é exatamente o mesmo valor; classNamedo atributo "class"). Outras propriedades obtêm seus valores iniciais de outras maneiras: Por exemplo, a parentNodepropriedade obtém seu valor com base no que é seu elemento pai;style propriedade, tenha ou não um atributo "estilo".

Vamos considerar essa âncora em uma página em http://example.com/testing.html:

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

Alguma arte ASCII gratuita (e deixando de fora muitas coisas):

+ −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
| HTMLAnchorElement |
+ −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
| href: "http://example.com/foo.html" |
| nome: "fooAnchor" |
| id: "fooAnchor" |
| className: "test one" |
| atributos: |
| href: "foo.html" |
| nome: "fooAnchor" |
| id: "fooAnchor" |
| classe: "teste um" |
+ −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

Observe que as propriedades e atributos são distintos.

Agora, embora sejam distintos, porque tudo isso evoluiu ao invés de ser projetado desde o início, várias propriedades retornam ao atributo do qual derivaram se você as definir. Mas nem todos o fazem, e como você pode ver de hrefcima, o mapeamento nem sempre é um "repasse de valor" direto, às vezes há interpretação envolvida.

Quando falo sobre propriedades como propriedades de um objeto, não estou falando em abstrato. Aqui está um código não-jQuery:

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

(Esses valores são como na maioria dos navegadores; há algumas variações.)

O linkobjeto é real e você pode ver que há uma distinção real entre acessar uma propriedade e acessar um atributo .

Como Tim disse, na grande maioria das vezes, queremos trabalhar com propriedades. Parcialmente, isso ocorre porque seus valores (até mesmo seus nomes) tendem a ser mais consistentes entre os navegadores. Na maioria das vezes, queremos trabalhar com atributos quando não há propriedade relacionada a ele (atributos personalizados) ou quando sabemos que, para esse atributo específico, o atributo e a propriedade não são 1: 1 (como emhref e "href" acima) .

As propriedades padrão estão dispostas nas várias especificações do DOM:

Essas especificações têm excelentes índices e eu recomendo manter os links à mão; Eu os uso o tempo todo.

Os atributos personalizados incluiriam, por exemplo, quaisquer data-xyzatributos que você possa colocar em elementos para fornecer metadados ao seu código (agora que é válido a partir do HTML5, desde que você mantenha o data-prefixo). (As versões recentes do jQuery dão acesso a data-xyzelementos por meio da datafunção, mas essa função não é apenas um acessador de data-xyzatributos [ele faz mais e menos que isso]; a menos que você realmente precise de seus recursos, eu usaria a attrfunção para interagir com data-xyzatributo.)

A attrfunção costumava ter uma lógica complicada em torno de obter o que eles pensavam que você queria, em vez de literalmente obter o atributo. Confundiu os conceitos. Mover-se para prope attrpretendia desconstruí-los. Resumidamente em v1.6.0 jQuery foi longe demais a esse respeito, mas a funcionalidade foi rapidamente adicionado de volta para attrlidar com as situações comuns onde as pessoas usam attrquando tecnicamente eles devem usar prop.

TJ Crowder
fonte
Uau. essa nova atualização 1.6.1 realmente anula um pouco essa questão .. (mas não muito), mas esse link basicamente responde agora
Naftali aka Neal
Não o anulou para mim, apenas corrigi um bug usando jquery1.7 onde estava configurando .attr ('class', 'bla') e não estava funcionando onde .prop ('className', 'bla' ) trabalhou
PandaWood 22/03
@PandaWood: .attr('class', 'bla')funciona como esperado para mim em 1.7.0 , 1.7.1 e 1.7.2 no Chrome 17, Firefox 11, Opera 11, IE6, IE8, IE9 e Safari 5.
TJ Crowder
Obrigado, deve haver algo específico no meu caso, deixe-me verificar isso e voltar com um caso de teste. Mas alterar o código como o temos agora, para simplesmente "prop / className", em vez de "attr", corrige um bug enorme para nós que atingimos quando passamos do jquery1.4 para o 1.7 - em todos os navegadores
PandaWood
3
@TJCrowder re: .data- lerá o valor padrão do atributo, se presente, mas se você escrever nele, ele mudará uma propriedade oculta do elemento e não atualizará o atributo.
Alnitak
250

Essa mudança foi um longo tempo para o jQuery. Durante anos, eles se contentaram com uma função chamada attr()que recuperou principalmente as propriedades do DOM, e não o resultado que você esperaria do nome. A segregação attr()e prop()deve ajudar a aliviar parte da confusão entre atributos HTML e propriedades DOM. $.fn.prop()agarra a propriedade DOM especificada, enquanto $.fn.attr()agarra o atributo HTML especificado.

Para entender completamente como eles funcionam, aqui está uma explicação detalhada sobre a diferença entre atributos HTML e propriedades DOM:

Atributos HTML

Sintaxe:

<body onload="foo()">

Objetivo: Permite que a marcação tenha dados associados a ela para eventos, renderização e outros fins.

Visualização: Atributos HTML O atributo de classe é mostrado aqui no corpo. É acessível através do seguinte código:

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

Os atributos são retornados no formato de sequência e podem ser inconsistentes de navegador para navegador. No entanto, eles podem ser vitais em algumas situações. Como exemplificado acima, o IE 8 Quirks Mode (e abaixo) espera o nome de uma propriedade DOM em get / set / removeAttribute em vez do nome do atributo. Essa é uma das muitas razões pelas quais é importante saber a diferença.

Propriedades do DOM

Sintaxe:

document.body.onload = foo;

Objetivo: fornece acesso às propriedades que pertencem aos nós do elemento. Essas propriedades são semelhantes aos atributos, mas são acessíveis apenas por JavaScript. Essa é uma diferença importante que ajuda a esclarecer o papel das propriedades do DOM. Observe que os atributos são completamente diferentes das propriedades , pois essa atribuição do manipulador de eventos é inútil e não receberá o evento (o corpo não possui um evento onload, apenas um atributo onload).

Visualização: Propriedades do DOM

Aqui, você verá uma lista de propriedades na guia "DOM" no Firebug. Essas são propriedades do DOM. Você notará imediatamente alguns deles, pois você os teria usado antes sem saber. Seus valores são o que você receberá por meio de JavaScript.

Documentação

Exemplo

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

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

Nas versões anteriores do jQuery, isso retorna uma string vazia. Em 1.6, ele retorna o valor adequado foo,.

Sem ter examinado o novo código para qualquer função, posso dizer com confiança que a confusão tem mais a ver com a diferença entre atributos HTML e propriedades DOM, do que com o próprio código. Felizmente, isso esclareceu algumas coisas para você.

-Matt

K.Dᴀᴠɪs
fonte
7
$.prop()obtém propriedades DOM, $.attr()obtém atributos HTML. Estou tentando preencher a lacuna psicologicamente para que você possa entender a diferença entre os dois.
10
Rapaz, eu também estou confuso agora. Então $('#test').prop('value')não retorna nada? Nem .attr('checked')para uma caixa de seleção? Mas costumava? Agora você teria que mudar para prop('checked')? Não compreendo a necessidade dessa distinção - por que é importante diferenciar entre atributos HTML e propriedades DOM? Qual é o caso de uso comum que fez essa alteração "há muito tempo" ? O que há de errado em abstrair a distinção entre os dois, já que parece que seus casos de uso se sobrepõem principalmente?
BlueRaja - Danny Pflughoeft
5
@BlueRaja: porque existe uma séria diferença subjacente entre os dois conceitos que, se você o esfregar debaixo do tapete como o jQuery costumava, resulta em falhas inesperadas. valueé um dos casos mais óbvios, pois a valuepropriedade fornecerá o valor atual de um campo, mas o valueatributo fornecerá o valor original que foi declarado no value="..."atributo, que é realmente odefaultValue propriedade. (Embora neste caso particular fica confuso novamente por bugs no IE <9.)
bobince
4
@BlueRaja: A resposta para isso é ainda mais complicada. :-) A configuração attr('value', ...)no jQuery <1.6 define a propriedade, portanto o valor atual é alterado e o valor padrão não. Na versão 1.6, ele define o atributo; portanto, em teoria, o valor padrão muda e o valor atual não. No entanto, existem (mais) inconsistências no navegador sobre o que exatamente define o valueatributo. No IE, também define o valor atual; em alguns navegadores, apenas define o valor atual se o valor atual ainda não tiver sido definido antes. [chora]
bobince
1
Assim como o @Quentin disse, "Os atributos são definidos pelo HTML. As propriedades são definidas pelo DOM". A versão mais simples que li.
Alan Dong
241

Uma propriedade está no DOM; um atributo está no HTML que é analisado no DOM.

Maiores detalhes

Se você alterar um atributo, a alteração será refletida no DOM (às vezes com um nome diferente).

Exemplo: Alterar o classatributo de uma tag altera a classNamepropriedade dessa tag no DOM. Se você não tiver nenhum atributo em uma tag, ainda terá a propriedade DOM correspondente com um valor vazio ou padrão.

Exemplo: enquanto sua tag não tem classatributo, a propriedade DOM classNameexiste com um valor de sequência vazio.

editar

Se você alterar um, o outro será alterado por um controlador e vice-versa. Este controlador não está no jQuery, mas no código nativo do navegador.

yunzen
fonte
Então, isso significa que é melhor atualizar o atributo porque você garante que o atributo e a propriedade sejam atualizados e estejam alinhados?
Lucas
1
@ Lucas, o DOM é a representação técnica interna, o modelo. Os atributos HTML são uma representação externa, uma visão. Se você alterar um, o outro será alterado por um controlador e vice-versa.
yunzen
@HerrSerker Então, ambos são mantidos sincronizados através de um controlador? Suponho que isso é apenas dentro dos métodos attr e prop do jQuery? Aqui está uma modificação do seu violino, onde eu exploro isso mais - jsfiddle.net/v8wRy - e até agora eles parecem equivalentes.
Luke
3
"Se você alterar um, o outro será alterado por um controlador e vice-versa. Este controlador não está no jQuery, mas no código nativo do navegador". Isso não é verdade para a maioria dos atributos / propriedades. Para a maioria, é apenas uma tradução unidirecional, em que um atributo determina o valor inicial da propriedade correspondente. As duas principais respostas explicam isso em detalhes.
ᴠɪɴᴄᴇɴᴛ
@Vincent. Não vejo, onde as duas principais respostas dizem algo contrário à minha resposta. Obviamente, a maioria dos atributos são os valores iniciais das propriedades DOM correspondentes. Mas eles são mutuamente dependentes. Experimente algo como jQuery('p').prop('className', 'foo');no console do Chrome e você verá como todos os parágrafos recebem o classatributo thg 'foo'. Claro que não no código fonte, que vem do servidor. Isso é uma constante.
usar o seguinte comando
140

É apenas a distinção entre atributos HTML e objetos DOM que causa confusão. Para aqueles que se sentem à vontade atuando nas propriedades nativas dos elementos DOM, como this.src this.value this.checkedetc,.prop é uma recepção calorosa à família. Para outros, é apenas uma camada adicional de confusão. Vamos esclarecer isso.

A maneira mais fácil de ver a diferença entre .attre .propé o seguinte exemplo:

<input blah="hello">
  1. $('input').attr('blah'): retorna 'hello'conforme o esperado. Não há surpresas aqui.
  2. $('input').prop('blah'): retorna undefined- porque está tentando fazer [HTMLInputElement].blah- e não existe essa propriedade nesse objeto DOM. Existe apenas no escopo como um atributo desse elemento, ou seja,[HTMLInputElement].getAttribute('blah')

Agora, mudamos algumas coisas assim:

$('input').attr('blah', 'apple');
$('input').prop('blah', 'pear');
  1. $('input').attr('blah'): retorna 'apple'eh? Por que não "pêra", como foi definido por último nesse elemento. Como a propriedade foi alterada no atributo de entrada, não no próprio elemento de entrada do DOM - eles basicamente quase funcionam independentemente um do outro.
  2. $('input').prop('blah'): retorna 'pear'

O que você realmente precisa ter cuidado é simplesmente não misturar o uso deles para a mesma propriedade em todo o aplicativo pelo motivo acima.

Veja um violino demonstrando a diferença: http://jsfiddle.net/garreh/uLQXc/


.attr vs .prop :

Rodada 1: estilo

<input style="font:arial;"/>
  • .attr('style') - retorna estilos embutidos para o elemento correspondente, ou seja "font:arial;"
  • .prop('style') - retorna um objeto de declaração de estilo, ou seja CSSStyleDeclaration

Rodada 2: valor

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

$('input').prop('value', 'i changed the value');
  • .attr('value') - retorna 'hello' *
  • .prop('value') - retorna 'i changed the value'

* Nota: o jQuery, por esse motivo, possui um .val()método que internamente é equivalente a.prop('value')

Gary Green
fonte
O @Neal porque ele faz referência melhor à estrutura da função jquery. "$ ('input'). prop ('blah'): retorna indefinido - porque está tentando fazer [HTMLInputElement] .blah - e não existe nenhuma propriedade nesse objeto DOM. Ele existe apenas no escopo como um atributo desse elemento, ou seja, [HTMLInputElement] .getAttribute ('blah') "
Uğur Gümüşhan
2
Parece diferente do doc, api.jquery.com/prop : "O método .prop () deve ser usado para definir desativado e verificado em vez do método .attr (). O método .val () deve ser usado para obter e valor de configuração ".
cisne
53

TL; DR

Use em prop()excesso attr()na maioria dos casos.

Uma propriedade é o estado atual do elemento de entrada. Um atributo é o valor padrão.

Uma propriedade pode conter itens de diferentes tipos. Um atributo pode conter apenas cadeias

agjmills
fonte
1
se possível, venha com poucas amostras fáceis do que você está dizendo e também mostre quando usar prop() and when to go for attr(). à espera da resposta :)
Mou 28/05
36

Verificação suja

Este conceito fornece um exemplo em que a diferença é observável: http://www.w3.org/TR/html5/forms.html#concept-input-checked-dirty

Experimente:

  • Clique no botão. Ambas as caixas de seleção foram marcadas.
  • desmarque as duas caixas de seleção.
  • clique no botão novamente. Somente a propcaixa de seleção foi marcada. 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>

Para alguns atributos como disabledon button, adicionar ou remover o atributo content disabled="disabled"sempre alterna a propriedade (chamada atributo IDL em HTML5) porque http://www.w3.org/TR/html5/forms.html#attr-fe-disabled diz:

O atributo IDL desativado deve refletir o atributo de conteúdo desativado.

portanto, você pode se safar, embora seja feio, pois modifica o HTML sem necessidade.

Para outros atributos como checked="checked"on input type="checkbox", as coisas quebram porque, quando você clica nele, ele fica sujo e, em seguida, adicionando ou removendo o checked="checked"atributo content não alterna mais a verificação .

É por isso que você deve usar principalmente .prop, pois afeta diretamente a propriedade efetiva, em vez de depender de efeitos colaterais complexos da modificação do HTML.

Ciro Santilli adicionou uma nova foto
fonte
Para completar também tentar essas variações: 1) Antes de clicar no botão de verificação e, em seguida, desmarque a primeira opção 2) (Para este você vai precisar alterar o snippet) Dê a primeira entrada de um checkedatributo:checked="checked"
ᴠɪɴᴄᴇɴᴛ
33

Tudo está no documento :

A diferença entre atributos e propriedades pode ser importante em situações específicas. Antes do jQuery 1.6, o método .attr () às vezes levava em consideração os valores das propriedades ao recuperar alguns atributos, o que poderia causar comportamento inconsistente. A partir do jQuery 1.6, o método .prop () fornece uma maneira de recuperar explicitamente os valores das propriedades, enquanto o .attr () recupera os atributos.

Então use prop!

Arnaud F.
fonte
2
Então isso significa que quando eu mudar para 1.6, muitas coisas vão quebrar?
Naftali aka Neal
Não, é apenas um comportamento inconsistente, se ele funciona antes, ele sempre trabalha com jQuery 1.6, é só que prop é mais seguro;)
Arnaud F.
6
Eu me lembro. $.attr()recuperando propriedades na maioria das vezes em que trabalhei com ela, não "às vezes". A confusão causada por isso ainda é ressonante hoje. Infelizmente, estou tendo muitos problemas para encontrar uma leitura definitiva sobre atributos HTML versus propriedades DOM, portanto, talvez eu escreva uma resposta aqui daqui a pouco.
3
@ Arnaud-f Não é verdade. Todo o código anterior à 1.6 que usa attr ('marcado') para marcar as caixas de seleção agora será quebrado.
CaptSaltyJack
3
@ Matt McDonald: Que tipo de "... problemas para encontrar uma solução definitiva? leitura sobre atributos HTML versus propriedades DOM ..." você quer dizer? As propriedades (refletidas ou não) são descritas na especificação HTML do DOM2 ; você também pode precisar para se referir aos DOM2 e DOM3 especificações.
TJ Crowder
28

atributos estão no seu documento / arquivo de texto HTML (== imagine que este é o resultado da sua marcação html analisada), enquanto as
propriedades estão na árvore HTML DOM (== basicamente uma propriedade real de algum objeto no sentido JS).

É importante ressaltar que muitos deles são sincronizados (se você atualizar a classpropriedade, o classatributo em html também será atualizado; caso contrário). Mas alguns atributos podem ser sincronizados com propriedades inesperadas - por exemplo, atributo checked corresponde à propriedade defaultChecked , para que

  • marcar manualmente uma caixa de seleção mudará de .prop('checked')valor, mas não mudará .attr('checked')e.prop('defaultChecked') valores
  • A configuração $('#input').prop('defaultChecked', true)também será alterada .attr('checked'), mas isso não será visível em um elemento.

A regra prática é : o .prop()método deve ser usado para atributos / propriedades booleanos e para propriedades que não existem em html (como window.location). Todos os outros atributos (aqueles que você pode ver no html) podem e devem continuar sendo manipulados com o .attr() método ( http://blog.jquery.com/2011/05/10/jquery-1-6-1-rc-1-released/ )

E aqui está uma tabela que mostra onde .prop()é preferido (mesmo que .attr()ainda possa ser usado).

tabela com uso preferido


Por que você às vezes deseja usar .prop () em vez de .attr (), onde este último é oficialmente recomendado?

  1. .prop()pode retornar qualquer tipo - string, número inteiro, booleano; while .attr()sempre retorna uma string.
  2. .prop()é dito ser cerca de 2,5 vezes mais rápido que .attr().
lakesare
fonte
algo foi alterado, como estes: $('#myImageId').prop('src', 'http://example.com/img.png'), var class = $('.myDivClass').prop('class')ou $('#myTextBox').prop('type', 'button'). E assim por diante ...
@ Mr.Wolf, desculpe, ainda não entendi o que você quer dizer. o que mudou'? sintaxe sempre foi assim.
usar o seguinte código
Penso que a tabela na sua resposta é desnecessária. Porque .prop()funciona bem com todas as propriedades. Você não quer marcar todas as propriedades na .prop()coluna, quer?
@ Mr.Wolf, eu acho que é necessário, porque, como já foi dito, é mostra onde .prop()é preferível (embora .attr()ainda pode ser usado) '
lakesare
Eu costumo usar .attr()para definir um evento que .prop()não pode. Como esta: $('.myDiv').attr('onclick', 'alert("Hello world!")'). Se você mudar .attr()para .prop(), não funcionará. Totalmente, acho que não há razão para usar .attr()para definir ou obter valor id/class/href/checked/src...... Observe que eu não digo que você está errado.
20

.attr():

  • Obtenha o valor de um atributo para o primeiro elemento no conjunto de elementos correspondentes.
  • Fornece o valor do elemento, conforme definido no html no carregamento da página

.prop():

  • Obtenha o valor de uma propriedade para o primeiro elemento no conjunto de elementos correspondentes.
  • Fornece os valores atualizados dos elementos que são modificados via javascript / jquery
Kgn-web
fonte
13

Normalmente você vai querer usar propriedades. Use atributos apenas para:

  1. Obtendo um atributo HTML personalizado (já que não é sincronizado com uma propriedade DOM).
  2. Obter um atributo HTML que não seja sincronizado com uma propriedade DOM, por exemplo, obter o "valor original" de um atributo HTML padrão, como <input value="abc">.
naor
fonte
7

attributes -> HTML

properties -> DOM

NkS
fonte
8
Eu sei o que você quer dizer, mas o HTML é uma linguagem de marcação e o DOM, uma representação criada a partir do HTML. Um DOMElement possui atributos e propriedades .
t.niese
@ t.niese, attirbutestambém uma das propriedades deDOM
NkS
A resposta curta é simples.
Nabi KAZ
6

Antes do jQuery 1.6, o attr()método algumas vezes considerava os valores das propriedades ao recuperar atributos, isso causava um comportamento inconsistente.

A introdução do prop()método fornece uma maneira de recuperar explicitamente os valores das propriedades, enquanto .attr()recupera atributos.

Os documentos:

jQuery.attr() Obtenha o valor de um atributo para o primeiro elemento no conjunto de elementos correspondentes.

jQuery.prop() Obtenha o valor de uma propriedade para o primeiro elemento no conjunto de elementos correspondentes.

Gothburz
fonte
3

Lembrete delicado sobre o uso prop(), exemplo:

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

A função acima é usada para verificar se a caixa de seleção1 está marcada ou não, se marcada: return 1; caso contrário: retorne 0. Função prop () usada aqui como uma função GET.

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

A função acima é usada para definir a caixa de seleção1 a ser marcada e retornar SEMPRE 1. Agora, a função prop () é usada como uma função SET.

Não estrague tudo.

P / S: Ao verificar a propriedade Image src . Se o src estiver vazio, prop retornará a URL atual da página (incorreta) e attr retornará uma string vazia (direita).

user2657778
fonte
Você está errado neste exemplo: <img src="smiley.gif" alt="Smiley face" width="42" height="42" onclick="alert($(this).prop('src'))">. Deve funcionar e retornar o local da imagem.
2

Uma coisa .attr()pode fazer isso .prop()não pode: afetar seletores CSS

Aqui está um problema que não vi nas outras respostas.

Seletor CSS [name=value]

  • responderá a .attr('name', 'value')
  • mas nem sempre para .prop('name', 'value')

.prop() afeta apenas alguns seletores de atributos

.attr() afeta todos os seletores de atributos

Bob Stein
fonte
0

1) Uma propriedade está no DOM; um atributo está no HTML que é analisado no DOM.

2) $ (elem) .attr ("marcado") (1.6.1+) "marcado" (String) Mudará com o estado da caixa de seleção

3) $ (elem) .attr ("marcado") (pré-1,6) true (Boolean) Alterado com o estado da caixa de seleção

  • Principalmente, queremos usar o objeto DOM em vez de atributos personalizados, como data-img, data-xyz.

  • Também algumas das diferenças ao acessar checkboxvalor e href com attr()e prop()como coisa mudam com a saída DOM com prop()o link completo de origine o Booleanvalor para a caixa de seleção (pre-1.6)

  • Só podemos acessar elementos DOM com propoutros, então ele forneceundefined

Parth Trivedi
fonte
0

Existem mais algumas considerações em prop () vs attr ():

  • selectedIndex, tagName, nodeName, nodeType, ownerDocument, defaultChecked e defaultSelected..etc devem ser recuperados e configurados com o método .prop (). Estes não têm atributos correspondentes e são apenas propriedades.

  • Caixa de seleção Para tipo de entrada

       .attr('checked') //returns  checked
       .prop('checked') //returns  true
       .is(':checked') //returns true
  • O método prop retorna o valor booleano para verificado, selecionado, desativado, readOnly..etc while attr retorna a sequência definida. Portanto, você pode usar diretamente .prop ('marcado') na condição if.

  • .attr () chama .prop () internamente, portanto o método .attr () será um pouco mais lento do que acessá-los diretamente por meio de .prop ().

Rishu Ranjan
fonte
-2

A resposta de Gary Hole é muito relevante para resolver o problema se o código for escrito dessa maneira

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

Como a função prop retorna o CSSStyleDeclarationobjeto, o código acima não funcionará corretamente em alguns navegadores (testado comIE8 with Chrome Frame Plugin no meu caso).

Assim, alterando-o para o seguinte código

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

resolveu o problema.

zawhtut
fonte