Introducción: ¿por qué es tan importante este tema?
\nSi alguna vez has escrito código jQuery que debía obtener o establecer el valor de un atributo en un elemento HTML, seguramente te has encontrado con dos métodos: .prop() y .attr(). A primera vista hacen lo mismo. Pero en la práctica, la diferencia entre ellos es la fuente de cientos de errores y miles de preguntas en Stack Overflow.
En este tutorial paso a paso entenderemos de una vez por todas en qué se diferencian .prop() y .attr() en jQuery, cuándo usar cada uno y cómo no caer en la trampa. Escribiremos código real, observaremos el comportamiento real del navegador y recordaremos una regla simple.
Este artículo no es documentación árida. Es tu guía personal sobre uno de los temas más confusos de jQuery.
\n\nBrevemente: atributos vs propiedades
\nAntes de sumergirnos en el código, analicemos la teoría. En el DOM (Modelo de Objetos del Documento) existen dos conceptos:
\n- \n
- Atributo (attribute) — lo que está escrito en el código HTML. Por ejemplo,
<input type="checkbox" checked="checked">. Los atributos siempre son cadenas de texto. \n - Propiedad (property) — lo que se almacena en el objeto del elemento DOM después de que el navegador ha leído el HTML. Las propiedades pueden ser de cualquier tipo de dato: cadena, booleano, número, objeto. \n
El método .attr() trabaja con atributos. El método .prop() trabaja con propiedades. ¿Suena simple? Sí, pero hay matices.
La trampa principal: atributos booleanos
\nEl ejemplo más popular que confunde a los principiantes son las casillas de verificación, los botones de radio y otros elementos con atributos booleanos (checked, disabled, selected, readonly).
Imagina que tienes este HTML:
\n<input type="checkbox" id="myCheckbox" checked>\nQuieres comprobar si la casilla está marcada. Lógicamente escribirías:
\nconsole.log( $('#myCheckbox').attr('checked') ); // "checked" (¡cadena!)\nconsole.log( $('#myCheckbox').prop('checked') ); // true (¡booleano!)\n¡Ahí está la diferencia! .attr() devuelve la cadena "checked" si el atributo está presente en el HTML, y undefined si no lo está. Mientras que .prop() devuelve true o false, dependiendo del estado actual del elemento en el DOM.
Ahora lo más interesante: ¿qué sucede si el usuario desmarca la casilla?
\n// Después de que el usuario desmarcó la casilla:\nconsole.log( $('#myCheckbox').attr('checked') ); // "checked"! (el HTML no cambió)\nconsole.log( $('#myCheckbox').prop('checked') ); // false (el estado cambió)\nPor eso usar .attr() para comprobar el estado de una casilla de verificación es un error. El atributo checked en el HTML permanece sin cambios, mientras que la propiedad checked en el DOM cambia dinámicamente. .prop() siempre da la respuesta actualizada.
La regla del pulgar
\nHay una regla simple que te ayudará a no equivocarte:
\n- \n
- Usa
.prop()cuando necesites obtener o cambiar el estado dinámico de un elemento (por ejemplo,checked,disabled,selected,valueen un input). \n - Usa
.attr()cuando necesites leer o cambiar un atributo estático del HTML (por ejemplo,href,src,data-*,id,class). \n
Recuerda: .prop() es para propiedades que cambian durante la ejecución. .attr() es para atributos definidos en el marcado.
Ejemplo paso a paso: trabajando con disabled
\nAnalicemos otro caso clásico: un botón con el atributo disabled.
<button id="myButton" disabled>Púlsame</button