jQuery Best Practices
This guide collects patterns used by professionals to write fast, accessible, and maintainable jQuery. Each topic includes an explanation, short example, and a Try it Yourself » demo.
Quick Reference
| Practice | Why it matters | Example |
|---|---|---|
| Cache selectors | Reduces repeated DOM queries; speeds up loops and handlers. | var $list = $('#list'); $list.append(...) |
| Event delegation | One handler works for current and future elements; lower memory. | $('#list').on('click', 'li.item', fn) |
| Namespace handlers | Easy to unbind specific features without breaking others. | $('#box').on('click.demo', fn); $('#box').off('click.demo') |
| Throttle / debounce | Prevents excessive work on scroll/resize/input. | $(win).on('scroll', throttle(fn, 100)) |
| Batch DOM updates | Minimizes layout thrash; big gains with large inserts. | Build HTML string/fragment and append once. |
detach() & reinsert |
Do heavy mutations off-DOM, then insert once. | var $tmp = $node.detach(); ... $('body').append($tmp) |
| Accessibility (ARIA) | Screen readers & keyboard users get feedback and focus. | <div role="status" aria-live="polite"> |
| Feature detect | Avoid brittle UA sniffing; adapt by capabilities. | if (window.fetch) { ... } |
| Promise error handling | Show user-friendly errors; avoid silent failures. | $.get(...).fail(xhr => show(xhr.status)) |
1) Cache jQuery selections
Query the DOM once and reuse the jQuery object. Build strings/fragments and append once instead of many small append() calls.
var $list = $('#list');
var html = [];
for(var i=0; i<200; i++){ html.push('<li>'+i+'</li>'); }
$list.append(html.join(''));
2) Use event delegation for dynamic content
Attach one handler on a stable parent; match children by selector. Works for elements added later.
$('#list').on('click', 'li.item', function(){ /* ... */ });
3) Namespace your handlers & cleanly unbind
Namespaced events avoid conflicts and allow safe teardown.
$('#box').on('click.demoNS', function(){ ... });
$('#box').off('click.demoNS');
4) Throttle and debounce high-frequency events
Throttle runs at most every N ms; debounce waits for quiet time. Great for scroll/resize and live search.
function throttle(fn, wait){ /* ... */ }
function debounce(fn, wait){ /* ... */ }
$(window).on('scroll', throttle(fn, 100));
$('#search').on('input', debounce(fn, 300));
5) Batch DOM updates
Build strings or use a DocumentFragment; append once. This avoids repeated style/layout recalculations.
var html = [];
for(var i=0; i<500; i++){ html.push('<div class="card">'+i+'</div>'); }
$('#wrap').append(html.join(''));
6) Do heavy work with detach() then reinsert
Mutate large subtrees off-DOM for speed; reinsert once.
var $tmp = $('#big').detach();
// mutate $tmp here...
$('body').append($tmp);
7) Accessibility: ARIA roles & focus management
Announce changes via live regions and keep logical focus order for keyboard users.
<div id="toast" role="status" aria-live="polite"></div>
8) Prefer feature detection over UA sniffing
Browsers vary; detect capabilities, not names.
if(window.fetch){ // use fetch, else use $.ajax fallback }
9) Promise-based error handling
Surface friendly errors; log details for debugging.
$.get('/api').done(function(data){ ... }).fail(function(xhr){ /* show xhr.status */ });