Which one do I use?
.attr()reads and writes what is in the HTML:href,aria-*,role. Screen readers and CSS selectors see these..prop()touches the live DOM object:checked,disabled,value,scrollHeight. Use it for state that changes after load..data()readsdata-*attributes (JSON is parsed for you) and stores anything โ objects, dates, functions โ against an element.
Leak-free by construction
Stored data lives in a WeakMap keyed by the element. When the element is gone, so is its data. Nothing is written onto your nodes, and there is no global cache to clean up.
Ada Lovelace
pro ยท 5 seats
View the source for this demo
<article id="user-card" class="plate" data-user='{"name":"Ada","plan":"pro","seats":5}' style="box-shadow:none">
<h4 style="margin:0">Ada Lovelace</h4>
<p class="plan muted" style="margin:4px 0 12px">pro ยท 5 seats</p>
<fieldset id="plan-fields" style="border:0;padding:0;display:flex;gap:16px;flex-wrap:wrap;align-items:center">
<legend class="sr-only">Plan settings</legend>
<label>Seats <input type="number" value="5" min="1" style="width:90px"></label>
<label><input type="checkbox" checked> Billing emails</label>
</fieldset>
</article>
<div class="row" style="margin-top:14px">
<button type="button" id="read">Read data</button>
<button type="button" id="upgrade">Upgrade plan</button>
<button type="button" id="lock">Lock fields</button>
<button type="button" id="fav" aria-pressed="false">โ Favourite</button>
</div>
<pre class="out" id="attr-out" aria-live="polite"></pre>const $card = $('#user-card');
function inspect(note) {
$('#attr-out').text(note + '\n\n' +
".data('user') โ " + JSON.stringify($card.data('user')) + '\n' +
".attr('data-user') โ " + $card.attr('data-user') + '\n' +
".prop('disabled') โ " + $('#plan-fields').prop('disabled') + '\n' +
".attr('aria-pressed') โ " + $('#fav').attr('aria-pressed'));
}
$('#read').on('click', () => inspect('data-* JSON is parsed into an object for you.'));
$('#upgrade').on('click', () => {
const user = $card.data('user');
$card.data('user', { ...user, plan: 'team', seats: user.seats + 5 }); // stored in a WeakMap
$card.find('.plan').text('team ยท ' + $card.data('user').seats + ' seats');
inspect('.data() stored a new object โ the HTML attribute is untouched.');
});
$('#lock').on('click', function () {
const locked = !$('#plan-fields').prop('disabled');
$('#plan-fields').prop('disabled', locked); // live DOM property
$(this).text(locked ? 'Unlock fields' : 'Lock fields');
inspect('.prop() flipped the live disabled property.');
});
$('#fav').on('click', function () {
const on = $(this).attr('aria-pressed') !== 'true';
$(this).attr('aria-pressed', String(on)).text(on ? 'โ
Favourite' : 'โ Favourite');
inspect('.attr() wrote aria-pressed โ screen readers announce the new state.');
});
inspect('Ready. Try the buttons.');More examples
Everyday calls
$('a.external').attr({ target: '_blank', rel: 'noopener' });
$('#agree').prop('checked'); // true / false
$('#save').prop('disabled', true);
$('#chart').data('series', bigArrayOfPoints); // any value, no serialization
$('#chart').removeData('series');API
Get an attribute from the first element, or set one or many on all elements.
Reference: .attr() โRemove an attribute from every element in the set.
Reference: .removeAttr() โGet or set a DOM property (as opposed to an HTML attribute) โ checked, disabled, selectedIndex, etc.
Read data-* attributes (JSON auto-parsed) or store arbitrary values against elements. Stored values live in a WeakMap โ no memory leaks, no cleanup.
Get or set form values. Checkboxes read/write booleans; multi-selects read as arrays.
Reference: .val() โMigrating
.data() behaves the same (JSON parsing, object stores). One deliberate difference: .val() on a checkbox returns true/false rather than its value attribute โ use .attr("value") if you need that.Related features
Classes & CSS
Toggle classes and set styles with addClass(), toggleClass() and css() โ including CSS custom properties, which jsKjs reads and writes without adding px..
Open โCoreForms & serialization
Turn forms into query strings or plain objects with serialize() and serializeObject(), then submit them with $.post โ or declaratively with kj-post..
Open โPulseReactive state
Declare state on an element with kj-data and every binding inside updates when it changes.
Open โ