The static jQuery.hasData() utility checks whether a DOM element already has jQuery internal data — without creating an empty cache entry like jQuery.data() does. This tutorial covers the official jQuery demo sequence, side-effect-free existence checks, plugin init guards, how event handlers affect the result, comparisons with .data() and jQuery.data(), and five practical try-it examples.
01
Boolean
true / false
02
Native el
DOM node
03
No side fx
Read-only
04
vs .data()
Pair API
05
Events count
.on / .off
06
Since 1.5
Core API
Fundamentals
Introduction
jQuery stores arbitrary JavaScript values and internal bookkeeping on DOM elements in a private cache. You normally read and write that cache with .data() on a jQuery collection or jQuery.data(element) on a raw node. But what if you only want to know whether data already exists — without accidentally creating an empty cache object?
That is exactly what jQuery.hasData( element ) does. Available since jQuery 1.5, it accepts a native DOM element and returns a Boolean: true when jQuery has associated internal data with that node, false when it has not. The check is read-only; it never initializes the cache.
Event handlers count too. Binding with .on() or .bind() associates internal data, so hasData returns true until you call .off() or remove the element. Browse the jQuery DOM hub, jQuery.data() utility, and .removeData() for the rest of the data API.
Concept
Understanding jQuery.hasData()
jQuery.hasData( element ) inspects jQuery’s private expando-backed store on a single DOM node. It returns true when any cached values or internal structures exist — including data set with jQuery.data(), values written via .data(), and the internal records created when event handlers are attached.
By contrast, calling jQuery.data( element ) on a pristine element always returns a data object (possibly empty) and may create cache entries as a side effect. Use hasData when the question is “does this element already have jQuery data?” rather than “give me the data object.”
💡
Beginner Tip
The official jQuery demo runs five steps on a <p> element: start false, set data → true, removeData → false, bind click → true, .off("click") → false. That sequence shows both stored values and event handlers affect the result.
Foundation
📝 Syntax
jQuery.hasData() has one form:
Check for internal data — since 1.5
jQuery
jQuery.hasData( element )
element — a native DOM element (not a jQuery object).
Returns — true if internal data exists; otherwise false.
Does not create or modify the cache.
Official hasData pattern
jQuery
var p = $( "p" )[ 0 ],
$p = $( p );
$.hasData( p ); // false
$.data( p, "testing", 123 );
$.hasData( p ); // true
$.removeData( p, "testing" );
$.hasData( p ); // false
$p.on( "click", function() {} );
$.hasData( p ); // true
$p.off( "click" );
$.hasData( p ); // false
Cheat Sheet
⚡ Quick Reference
Goal
Code
Check if element has data
jQuery.hasData( el )
Get native element from jQuery
var el = $("#box")[0]
Set data (creates cache)
jQuery.data( el, "key", value )
Remove one key
jQuery.removeData( el, "key" )
Collection equivalent for data
$("#box").data("key", value)
Events also create data
$("#box").on("click", fn) → hasData true
Compare
📋 jQuery.hasData() vs jQuery.data() vs .data() vs .removeData()
Four related data APIs — know when to check, read, write, or delete.
jQuery.hasData()
exists?
Boolean check on a native element — no cache creation, read-only
jQuery.data()
get / set
Static utility on a DOM element — may create cache on first access
.data()
collection
Get or set cached values on matched elements — also reads data-* attrs
.removeData()
delete
Clear cached keys on a jQuery collection — pair with hasData for audits
Hands-On
Examples Gallery
Example 1 follows the official jQuery API documentation. Examples 2–5 cover side-effect-free checks, plugin init guards, event-handler data, and batch cleanup audits. Use DevTools or the Try-it links to run each snippet in the browser.
📚 Getting Started
Official jQuery demo and the read-only check pattern.
Example 1 — Official Demo: Five-Step Sequence
Run the exact sequence from the jQuery API docs: data, removeData, bind, and unbind each flip the Boolean result.
jQuery
var p = $( "p" )[ 0 ],
$p = $( p );
$.hasData( p ); // false
$.data( p, "testing", 123 );
$.hasData( p ); // true
$.removeData( p, "testing" );
$.hasData( p ); // false
$p.on( "click", function() {} );
$.hasData( p ); // true
$p.off( "click" );
$.hasData( p ); // false
Step 1: hasData → false (pristine element)
Step 2: after $.data("testing", 123) → true
Step 3: after $.removeData("testing") → false
Step 4: after .on("click") → true
Step 5: after .off("click") → false
Both stored values and event bindings affect the result
How It Works
Each mutation to jQuery’s internal store toggles whether hasData returns true. Removing the last cached value and all event bookkeeping returns the element to a “no data” state from jQuery’s perspective.
Example 2 — Avoid Accidental Cache Creation
Use hasData instead of jQuery.data() when you only need an existence check on a pristine element.
jQuery
var el = document.getElementById( "box" );
// WRONG for a pure existence check — may create empty cache
// var obj = jQuery.data( el );
// var has = obj && Object.keys( obj ).length > 0;
// RIGHT — read-only Boolean, no side effects
var has = jQuery.hasData( el ); // false on pristine element
if ( !has ) {
console.log( "Safe to initialize — no jQuery data yet" );
}
Before any jQuery calls: hasData → false
After jQuery.data(el) read (no keys set): hasData → true (cache created!)
After jQuery.hasData(el) on fresh element: stays false
Use hasData when you must not touch the cache
How It Works
jQuery.data(element) without a key name returns the data object and initializes internal structures. jQuery.hasData(element) answers the yes/no question without that overhead — ideal for guards in library code.
📈 Practical Patterns
Plugin guards, event data, and cleanup audits.
Example 3 — Plugin Init Guard
Skip initialization when the element already has jQuery data from a prior run.
jQuery
function initTabs( $root ) {
var el = $root[ 0 ];
if ( jQuery.hasData( el ) && $root.data( "tabs" ) ) {
return; // already initialized
}
$root.data( "tabs", { active: 0 } );
$root.on( "click.tabs", ".tab", function() { /* ... */ } );
}
initTabs( $( "#nav" ) );
initTabs( $( "#nav" ) ); // second call is a no-op
First initTabs(): hasData false → plugin runs, sets data + binds events
Second initTabs(): hasData true + data("tabs") exists → skipped
Prevents double-binding and duplicate widget state
How It Works
Combine hasData with a named plugin key for a cheap first-pass check. After the first init, both stored tabs data and namespaced event handlers keep hasData true until you tear the plugin down.
Example 4 — Event Handlers Create Internal Data
Binding a click handler makes hasData true even when no custom keys were set.
jQuery
var el = $( "#btn" )[ 0 ],
$btn = $( el );
jQuery.hasData( el ); // false
$btn.on( "click", function() {
alert( "Clicked!" );
});
jQuery.hasData( el ); // true
$btn.off( "click" );
jQuery.hasData( el ); // false
Before .on("click"): hasData → false
After .on("click"): hasData → true (handler bookkeeping)
After .off("click"): hasData → false
Event bindings alone can make hasData true
How It Works
jQuery’s event system stores handler lists in the same internal layer that hasData inspects. Always unbind with .off() during teardown if you expect hasData to return false afterward.
Example 5 — Batch Audit Before Cleanup
Loop over candidate elements and log which ones still hold jQuery data before a page section is destroyed.
jQuery
function auditSection( selector ) {
var withData = [];
$( selector ).each(function() {
if ( jQuery.hasData( this ) ) {
withData.push( this.id || this.className || "anonymous" );
}
});
return withData;
}
// Before tearing down #sidebar widgets
var dirty = auditSection( "#sidebar [data-widget]" );
console.log( "Elements with jQuery data:", dirty );
Inside .each(), this is already a native DOM element — perfect for jQuery.hasData(this). Use the audit list to call .removeData() and .off() only where needed before removing nodes from the page.
Applications
🚀 Common Use Cases
Plugin init guards — skip double initialization when data or handlers already exist.
Side-effect-free checks — test pristine elements without calling jQuery.data().
Teardown audits — find elements that still hold cache before removing a DOM subtree.
Debugging — quickly see whether jQuery has touched an element in DevTools-driven scripts.
Memory hygiene — identify leaked widgets that forgot to call .removeData() or .off().
Library code — low-level utilities that receive raw DOM nodes from non-jQuery callers.
🧠 How jQuery.hasData() Inspects the Cache
1
Receive native element
Pass a DOM node — not a jQuery collection.
element
2
Look up internal store
jQuery checks its private expando-backed cache and event bookkeeping.
Cache
3
Return Boolean only
No objects created, no keys read, no DOM changes.
Read-only
4
✓
true or false
true when any internal data exists; false when the element is untouched by jQuery’s cache layer.
Important
📝 Notes
Available since jQuery 1.5; stable across 1.x, 2.x, 3.x, and 4.x.
Requires a native DOM element — use $("#el")[0] or collection.get(0).
Never creates cache entries; safe for existence checks on pristine nodes.
Event handlers from .on() / .bind() make hasData return true.
HTML data-* attributes alone do not flip the result until .data() reads them.
Pair with jQuery.removeData() or .removeData() to clear values after auditing.
.remove() cleans up automatically; detached nodes may still report true until cleared.
Compatibility
Browser Support
jQuery.hasData() has been part of jQuery since 1.5+. It operates on jQuery's internal data layer, not browser-specific APIs. Works in all browsers supported by your jQuery build — IE6+ through modern evergreen browsers in legacy jQuery versions, and all current browsers in jQuery 3.x and 4.x.
✓ jQuery 1.5+
jQuery.hasData()
Universal read-only data-existence check across jQuery 1.x, 2.x, 3.x, and 4.x. Use before jQuery.data() when you must not create an empty cache.
100%With jQuery loaded
Google ChromeAll versions · Desktop & Mobile
Full support
Mozilla FirefoxAll versions · Desktop & Mobile
Full support
Apple SafariAll versions · macOS & iOS
Full support
Microsoft EdgeAll versions · Chromium & Legacy
Full support
Internet ExplorerIE 6+ · Legacy environments
Full support
OperaAll modern versions
Full support
jQuery.hasData()Universal
Bottom line: Default choice when you need a side-effect-free Boolean check on a native DOM element.
Wrap Up
Conclusion
The jQuery hasData() utility answers a simple question: does this DOM element already have internal jQuery data? It returns a Boolean without creating cache entries — unlike jQuery.data(element), which always hands back a data object. The official five-step demo shows how stored values and event handlers both affect the result.
Use hasData for plugin guards and cleanup audits, then reach for .data() to read or write values and .removeData() to delete them. That trio covers the full element-data lifecycle in jQuery.
Pass a native DOM element — $("#el")[0] or this inside .each()
Use hasData before init when double-binding must be avoided
Combine with a named plugin key via .data("plugin") for precise guards
Call .off() during teardown so hasData can return false
Audit sections with hasData before bulk DOM removal
❌ Don’t
Pass a jQuery object — unwrap with [0] or .get(0) first
Use jQuery.data(el) just to check existence — it may create cache
Assume false means no event handlers were ever bound on a reused node
Expect hasData to read HTML data-* attributes directly
Forget detached elements may still report true until explicitly cleared
Summary
Key Takeaways
Knowledge Unlocked
Six things to remember about jQuery.hasData()
The read-only existence check for jQuery’s internal element cache.
6
Core concepts
?01
Boolean
true / false
Check
DOM02
Native el
Not jQuery
Input
∅03
No side fx
Read-only
Safe
↔04
vs .data()
Pair API
Compare
⚡05
Events
.on counts
Handlers
1.506
Since 1.5
Core API
Stable
❓ Frequently Asked Questions
jQuery.hasData(element) returns true when the given DOM element has any data in jQuery's internal cache — including values set with jQuery.data() or .data(), and internal bookkeeping from bound event handlers. It returns false when no cache exists. Available since jQuery 1.5.
jQuery.hasData(element) only checks — it never creates a data object. jQuery.data(element) always returns a data object and may create an empty one on first access even if the element had no data before. Use hasData when you want a read-only existence check without side effects.
Yes. When you bind events with .on(), .bind(), or similar methods, jQuery associates internal data with the element. jQuery.hasData() returns true until those handlers are removed with .off() or the element is cleaned up with .remove().
No. jQuery.hasData() expects a native DOM element, not a jQuery collection. Pass the raw node — for example, var el = document.getElementById('box') or $('#box')[0]. The collection method .data() works on jQuery objects; hasData is the static low-level checker.
Use it before calling jQuery.data() when you only need to know whether data already exists — plugin init guards, cleanup audits, and avoiding accidental cache creation on pristine elements. Pair with jQuery.removeData() or .removeData() when you need to clear data afterward.
Not directly. hasData reports whether jQuery's internal cache exists on the element. A data-* attribute alone does not create cache until .data() or jQuery.data() reads it. Once cached — including from attributes or event bindings — hasData returns true until the cache is cleared.
Did you know?
Calling jQuery.data( element ) with no key on a brand-new element still initializes jQuery’s internal cache — so a subsequent jQuery.hasData( element ) returns true even though you never stored a value. That is why plugin authors prefer hasData for existence checks. Event handlers create the same effect: a lone .on( "click", fn ) is enough for hasData to report true until .off( "click" ) runs.