jQuery / Method / .prop() - Read and Set DOM Properties
jQuery’s .prop("name") reads a DOM property from the first selected element; .prop("name", value) sets it on every selected element. Use .prop("checked") for a checkbox’s current checked state and .prop("disabled") for its disabled state. Distinguish current properties managed by the browser from attribute strings written in HTML.
Current state versus HTML attributes
The Document Object Model (DOM) represents an HTML document as nodes and objects. Properties in the .prop() API include checked, disabled and selectedIndex on these objects. .attr() reads and sets HTML attributes. Matching names do not always mean the same current state.
| Question | Method | Meaning |
|---|---|---|
| Currently checked? | .prop("checked") | Current Boolean true/false |
| Default checked state? | .prop("defaultChecked") | Default corresponding to the HTML checked attribute |
| HTML attribute itself? | .attr("checked") or getAttribute("checked") | Attribute that does not follow user clicks |
| Form control value? | .val() | Value or selected value, separate from checked state |
<input type="checkbox" checked=""> starts checked. Unchecking it changes the checked property to false while defaultChecked and the attribute remain unchanged. The checkbox checked attribute is Boolean: presence matters, so checked="false" does not mean unchecked.
Do not use the string returned by .attr("checked") as the current state. With checked="" here, jQuery 3.7.1 returned "checked" and 4.0.0 returned the empty string "". An empty string is falsy in JavaScript even when the checkbox is checked. Read the Boolean .prop("checked") rather than comparing version-dependent attribute strings.
Complete example of state and change events
Save all code as UTF-8 in prop-demo.html and open it in a browser. Internet is required for the official jQuery file 4.0.0 from its content delivery network (CDN); no installation is needed. These interactions and Console snippets were executed with 3.7.1 and 4.0.0. Native getAttribute() displays the attribute consistently across both versions.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Read and change DOM properties</title>
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<style>
body { font: 16px/1.6 sans-serif; max-width: 760px; margin: 24px auto; padding: 16px; }
button { font: inherit; margin: 4px; max-width: 100%; }
label { display: block; padding: 12px; border: 1px solid #aab; }
pre { white-space: pre-wrap; overflow-wrap: anywhere; }
</style>
</head>
<body>
<h1>Current properties and markup attributes</h1>
<form id="demo-form">
<label><input type="checkbox" id="subscribe" name="subscription" value="weekly" checked=""> Weekly subscription</label>
</form>
<button type="button" id="toggle">Toggle checked</button>
<button type="button" id="set">Set unchecked and disabled</button>
<button type="button" id="enable">Enable</button>
<button type="button" id="notify">Check and trigger change</button>
<button type="button" id="reset">Reset</button>
<pre id="result" aria-live="polite"></pre>
<script>
$(function () {
const $box = $("#subscribe");
let changes = 0;
function report() {
$("#result").text(`checked=${$box.prop("checked")}\ndefaultChecked=${$box.prop("defaultChecked")}\nchecked attribute=${JSON.stringify($box.get(0).getAttribute("checked"))}\ndisabled=${$box.prop("disabled")}\nvalue=${$box.val()}\nchange events=${changes}`);
}
$box.on("change", function () { changes++; report(); });
$("#toggle").on("click", function () { $box.prop("checked", function (index, old) { return !old; }); report(); });
$("#set").on("click", function () { $box.prop({ checked: false, disabled: true }); report(); });
$("#enable").on("click", function () { $box.prop("disabled", false); report(); });
$("#notify").on("click", function () { $box.prop("checked", true).trigger("change"); });
$("#reset").on("click", function () { $("#demo-form").get(0).reset(); $box.prop("disabled", false); changes = 0; report(); });
report();
});
</script>
</body>
</html>
Initial output follows. Two quotes after checked attribute mean the attribute exists with an empty string value. If absent, getAttribute() would return null.
checked=true
defaultChecked=true
checked attribute=""
disabled=false
value=weekly
change events=0
- Toggle checked changes checked to false, preserving the default, attribute and value. change events remains zero.
- Check the box directly: change events increases by one. Compare a state change with an event notification separately.
- Set unchecked and disabled applies .prop({ checked: false, disabled: true }). The box becomes unchecked and cannot be directly operated.
- Enable sets disabled to false without also checking the box.
- Check and trigger change sets checked to true and explicitly triggers change, increasing the counter. Setting a property alone does not run the change handler.
- Reset restores the form’s default checked state, separately clears disabled and zeroes the counter. Repeated resets restore the same initial output.
Do not assume form reset() also restores disabled; the example clears it explicitly. Triggering change notifies registered event handlers, rather than reproducing an entire physical pointer interaction. If updating a related display is sufficient after your code changes a property, call a display function such as report() directly.
Object setters, callbacks and selectedIndex
Use an object for several properties and a function for element-specific values. The callback receives the collection’s zero-based index and the previous value; its return becomes the new property. After Reset, run this complete snippet in the developer tools Console. It creates two temporary checkboxes, reverses their states, disables them and removes them at the end.
const $holder = $('<div><input type="checkbox" checked><input type="checkbox"></div>').appendTo("body");
const $boxes = $holder.find("input");
console.log(`before=${$boxes.map(function () { return this.checked; }).get().join(",")}`);
$boxes.prop("checked", function (index, old) { return !old; });
$boxes.prop({ disabled: true });
console.log(`after=${$boxes.map(function () { return this.checked; }).get().join(",")}`);
console.log(`first getter=${$boxes.prop("checked")}; type=${typeof $boxes.prop("checked")}`);
console.log(`disabled count=${$boxes.filter(":disabled").length}`);
console.log(`empty getter=${typeof $().prop("checked")}`);
$holder.remove();
before=true,false
after=false,true
first getter=false; type=boolean
disabled count=2
empty getter=undefined
The getter .prop("checked") returns only the first element’s false, while the setter affects both. For every state, read each with .map() or .each(). Do not infer that all boxes are unchecked from the first box alone.
A select’s selectedIndex is a property, with zero for its first option. .val() reads the selected option’s value. This Console snippet selects the second option, reports its index and value, then removes the temporary control.
const $select = $('<select><option value="a">Alpha</option><option value="b">Beta</option></select>').appendTo("body");
$select.prop("selectedIndex", 1);
console.log(`index=${$select.prop("selectedIndex")}; value=${$select.val()}`);
$select.remove();
index=1; value=b
Troubleshoot values that seem unchanged
Pass Boolean false to checked and disabled, not the string "false". In the tested environment, .prop("checked", "false") coerced the string to true and checked the box. Set built-in state explicitly, such as .prop("disabled", false), instead of removing built-in checked or disabled properties.
The getter on an empty selection returns undefined. Distinguish this from false, which is a valid unchecked state. If a target should exist, check its selector, .length and DOM-ready timing. Decide whether you need an HTML attribute or a DOM property; do not mix arbitrary data-* attribute handling with current checked state.




