19 KiB
jQuery 4.0.0 Documentation
Release Date: January 17, 2026 License: MIT 20th Anniversary Release
Table of Contents
Overview
jQuery 4.0.0 marks a significant milestone—celebrating jQuery's 20th anniversary and the first major version release in nearly 10 years. This release modernizes the library by removing legacy browser support, adopting ES modules, and improving security features.
Key Highlights
- Modernized codebase migrated from AMD to ES modules
- Smaller bundle size with improved slim build
- Enhanced security with Trusted Types and CSP support
- Removed deprecated APIs in favor of native JavaScript equivalents
- Updated browser support dropping legacy browsers
Installation
CDN
<!-- Full version -->
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<!-- Slim version (no Deferreds/Callbacks, ~8kb smaller) -->
<script src="https://code.jquery.com/jquery-4.0.0.slim.min.js"></script>
npm
npm install jquery@4.0.0
ES Module Import
// Full import
import $ from 'jquery';
// Named import
import { jQuery } from 'jquery';
CommonJS
const $ = require('jquery');
Browser Support
Supported Browsers
| Browser | Minimum Version |
|---|---|
| Chrome | Last 3 versions |
| Firefox | Last 2 versions + ESR |
| Safari | Last 3 versions |
| Edge (Chromium) | Last 3 versions |
| iOS Safari | Last 3 versions |
| Android Chrome | Last 3 versions |
Removed Support
The following browsers are no longer supported:
- Internet Explorer 10 and earlier (IE 11 support planned for removal in jQuery 5.0)
- Edge Legacy (non-Chromium)
- iOS versions older than the last 3
- Firefox versions older than the last 2 (except ESR)
- Android Browser (AOSP)
Breaking Changes
1. Removed Deprecated Utility Functions
Several utility functions deprecated in previous versions have been removed. Use native JavaScript equivalents instead.
| Removed Function | Native Replacement |
|---|---|
jQuery.isArray() |
Array.isArray() |
jQuery.parseJSON() |
JSON.parse() |
jQuery.trim() |
String.prototype.trim() |
jQuery.type() |
typeof / instanceof |
jQuery.now() |
Date.now() |
jQuery.isNumeric() |
!isNaN(parseFloat(n)) && isFinite(n) |
jQuery.isFunction() |
typeof fn === 'function' |
jQuery.isWindow() |
obj != null && obj === obj.window |
Example Migration
// jQuery 3.x (deprecated)
if ($.isArray(myVar)) { /* ... */ }
if ($.isFunction(callback)) { /* ... */ }
var trimmed = $.trim(userInput);
var data = $.parseJSON(jsonString);
var timestamp = $.now();
// jQuery 4.0 (use native)
if (Array.isArray(myVar)) { /* ... */ }
if (typeof callback === 'function') { /* ... */ }
var trimmed = userInput.trim();
var data = JSON.parse(jsonString);
var timestamp = Date.now();
2. Focus Event Order Change
The focus-related event order now follows the W3C specification.
// jQuery 3.x order:
// focusout → blur → focusin → focus
// jQuery 4.0 order (W3C compliant):
// blur → focusout → focus → focusin
Example: Observing Event Order
const $input = $('#myInput');
$input.on('blur', () => console.log('1. blur'));
$input.on('focusout', () => console.log('2. focusout'));
$input.on('focus', () => console.log('3. focus'));
$input.on('focusin', () => console.log('4. focusin'));
// When focus moves from #myInput to another element:
// Output in jQuery 4.0:
// 1. blur
// 2. focusout
// Then when new element receives focus:
// 3. focus
// 4. focusin
3. Removed Array Methods from jQuery Prototype
The push, sort, and splice methods have been removed from the jQuery prototype.
// jQuery 3.x
$elements.push(newElement);
$elements.sort(compareFn);
$elements.splice(0, 1);
// jQuery 4.0
[].push.call($elements, newElement);
[].sort.call($elements, compareFn);
[].splice.call($elements, 0, 1);
// Or convert to array first
const elemArray = $elements.toArray();
elemArray.push(newElement);
New Features
1. ES Module Support
jQuery 4.0 source has been migrated from AMD to ES modules, enabling better integration with modern build tools.
Using with Modern Bundlers
// Rollup, Webpack, Vite, etc.
import $ from 'jquery';
$(document).ready(() => {
console.log('jQuery 4.0 with ES modules!');
});
Dynamic Import
// Lazy load jQuery when needed
async function initializeUI() {
const { default: $ } = await import('jquery');
$('.dynamic-content').fadeIn();
}
2. Trusted Types Support
jQuery 4.0 adds support for Trusted Types, enhancing security in environments with strict Content Security Policies.
// jQuery now accepts TrustedHTML objects
const policy = trustedTypes.createPolicy('myPolicy', {
createHTML: (string) => DOMPurify.sanitize(string)
});
const trustedContent = policy.createHTML('<p>Safe content</p>');
$('#container').html(trustedContent);
3. Improved CSP Compatibility
Async script requests now use <script> tags instead of inline scripts to avoid CSP violations.
// Scripts loaded via $.getScript() now comply with CSP
$.getScript('https://example.com/script.js')
.done(() => console.log('Script loaded (CSP compliant)'))
.fail(() => console.error('Script failed to load'));
4. Smaller Slim Build
The slim build now excludes Deferreds and Callbacks, reducing the gzipped size by approximately 8kb.
<!-- Regular: ~30kb gzipped -->
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<!-- Slim: ~19.5kb gzipped -->
<script src="https://code.jquery.com/jquery-4.0.0.slim.min.js"></script>
Slim build excludes:
- Ajax module
- Effects/animation module
- Deferreds
- Callbacks
Migration Guide
Using jQuery Migrate Plugin
For gradual migration, use the jQuery Migrate plugin to identify deprecated features:
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script src="https://code.jquery.com/jquery-migrate-4.0.0.min.js"></script>
The Migrate plugin will log warnings to the console for deprecated usage.
Step-by-Step Migration
Step 1: Update Utility Function Calls
// Before (jQuery 3.x)
function processData(data) {
if ($.isArray(data)) {
return data.map(item => $.trim(item));
}
return $.trim(data);
}
// After (jQuery 4.0)
function processData(data) {
if (Array.isArray(data)) {
return data.map(item => item.trim());
}
return data.trim();
}
Step 2: Update Type Checking
// Before (jQuery 3.x)
function handleCallback(callback) {
if ($.isFunction(callback)) {
callback();
}
}
function getType(value) {
return $.type(value); // "array", "date", "regexp", etc.
}
// After (jQuery 4.0)
function handleCallback(callback) {
if (typeof callback === 'function') {
callback();
}
}
function getType(value) {
if (Array.isArray(value)) return 'array';
if (value instanceof Date) return 'date';
if (value instanceof RegExp) return 'regexp';
return typeof value;
}
Step 3: Handle Focus Event Order Changes
// If your code depends on specific event order, update accordingly
$('#form-field').on('focusout', function() {
// In jQuery 4.0, blur fires BEFORE focusout
// Adjust validation logic if needed
validateField(this);
});
Step 4: Update Array Method Usage
// Before (jQuery 3.x)
const $items = $('.item');
$items.push(document.createElement('div'));
// After (jQuery 4.0) - Option 1: Use native call
const $items = $('.item');
[].push.call($items, document.createElement('div'));
// After (jQuery 4.0) - Option 2: Use .add()
const $items = $('.item').add(document.createElement('div'));
API Reference
Core Functions
jQuery(selector [, context])
Select elements from the DOM.
// Select by ID
const $header = $('#header');
// Select by class
const $buttons = $('.btn');
// Select by tag
const $paragraphs = $('p');
// Select with context
const $items = $('.item', '#container');
// Create elements
const $newDiv = $('<div class="new">Content</div>');
jQuery.noConflict([removeAll])
Relinquish jQuery's control of the $ variable.
const jq = $.noConflict();
jq('#element').addClass('active');
// With removeAll=true, also removes 'jQuery' global
const jq = jQuery.noConflict(true);
Utilities
jQuery.extend([deep], target, object1 [, objectN])
Merge objects into the target object.
// Shallow merge
const defaults = { color: 'blue', size: 'medium' };
const options = { color: 'red' };
const settings = $.extend({}, defaults, options);
// Result: { color: 'red', size: 'medium' }
// Deep merge
const obj1 = { a: { b: 1, c: 2 } };
const obj2 = { a: { b: 3 } };
const result = $.extend(true, {}, obj1, obj2);
// Result: { a: { b: 3, c: 2 } }
jQuery.each(collection, callback)
Iterate over arrays or objects.
// Array iteration
$.each(['a', 'b', 'c'], function(index, value) {
console.log(`${index}: ${value}`);
});
// Object iteration
$.each({ name: 'John', age: 30 }, function(key, value) {
console.log(`${key}: ${value}`);
});
// Return false to break the loop
$.each([1, 2, 3, 4, 5], function(i, num) {
if (num > 3) return false;
console.log(num);
});
// Output: 1, 2, 3
jQuery.map(array, callback)
Transform array elements.
const numbers = [1, 2, 3, 4];
const doubled = $.map(numbers, n => n * 2);
// Result: [2, 4, 6, 8]
// Can return multiple values
const expanded = $.map([1, 2], n => [n, n * 2]);
// Result: [1, 2, 2, 4]
// Return null to remove item
const filtered = $.map([1, 2, 3, 4], n => n > 2 ? n : null);
// Result: [3, 4]
jQuery.grep(array, function [, invert])
Filter array elements.
const numbers = [1, 2, 3, 4, 5, 6];
// Keep elements where callback returns true
const evens = $.grep(numbers, n => n % 2 === 0);
// Result: [2, 4, 6]
// With invert=true, keep elements where callback returns false
const odds = $.grep(numbers, n => n % 2 === 0, true);
// Result: [1, 3, 5]
jQuery.merge(first, second)
Merge two arrays.
const arr1 = [1, 2];
const arr2 = [3, 4];
$.merge(arr1, arr2);
// arr1 is now [1, 2, 3, 4]
// Works with array-like objects
const $divs = $('div');
const $spans = $('span');
$.merge($divs, $spans);
jQuery.inArray(value, array [, fromIndex])
Find value index in array.
const arr = ['a', 'b', 'c', 'd'];
$.inArray('b', arr); // Returns: 1
$.inArray('x', arr); // Returns: -1
$.inArray('b', arr, 2); // Returns: -1 (starts search at index 2)
jQuery.isPlainObject(obj)
Check if value is a plain object.
$.isPlainObject({}); // true
$.isPlainObject({ a: 1 }); // true
$.isPlainObject(new Object()); // true
$.isPlainObject([]); // false
$.isPlainObject(document.body); // false
$.isPlainObject(new Date()); // false
jQuery.isEmptyObject(obj)
Check if object has no properties.
$.isEmptyObject({}); // true
$.isEmptyObject({ a: 1 }); // false
$.isEmptyObject([]); // true (arrays are objects)
Callbacks Object
jQuery.Callbacks(flags)
Create a callback list with optional flags.
Flags:
once: Callbacks fire only oncememory: Remember previous values and call new callbacks immediatelyunique: Prevent duplicate callbacksstopOnFalse: Stop firing when a callback returns false
// Basic usage
const callbacks = $.Callbacks();
function fn1(value) {
console.log('fn1:', value);
}
function fn2(value) {
console.log('fn2:', value);
}
callbacks.add(fn1);
callbacks.add(fn2);
callbacks.fire('hello');
// Output:
// fn1: hello
// fn2: hello
// With flags
const onceCallbacks = $.Callbacks('once');
onceCallbacks.add(fn1);
onceCallbacks.fire('first'); // fn1: first
onceCallbacks.fire('second'); // (nothing - already fired)
// Memory flag - useful for ready-like patterns
const memoryCallbacks = $.Callbacks('memory');
memoryCallbacks.fire('done');
memoryCallbacks.add(fn1); // Immediately called with 'done'
Deferred Object
jQuery.Deferred([beforeStart])
Create a Deferred object for async operations.
function asyncOperation() {
const deferred = $.Deferred();
setTimeout(() => {
const success = Math.random() > 0.5;
if (success) {
deferred.resolve('Operation succeeded');
} else {
deferred.reject('Operation failed');
}
}, 1000);
return deferred.promise();
}
asyncOperation()
.done(result => console.log(result))
.fail(error => console.error(error))
.always(() => console.log('Complete'));
jQuery.when(deferreds)
Execute callback when all Deferreds resolve.
function fetchUser() {
return $.ajax('/api/user');
}
function fetchPosts() {
return $.ajax('/api/posts');
}
$.when(fetchUser(), fetchPosts())
.done((userData, postsData) => {
console.log('User:', userData[0]);
console.log('Posts:', postsData[0]);
})
.fail(() => {
console.error('One or more requests failed');
});
DOM Ready
jQuery(callback) / jQuery.ready
Execute code when DOM is ready.
// Shorthand (recommended)
$(function() {
console.log('DOM ready');
});
// Explicit ready
$(document).ready(function() {
console.log('DOM ready');
});
// Arrow function
$(() => {
console.log('DOM ready');
});
// Multiple ready handlers are executed in order
$(() => console.log('First'));
$(() => console.log('Second'));
Data Storage
.data(key, value) / .data(key) / .data()
Store and retrieve data associated with elements.
// Set data
$('#element').data('userId', 123);
$('#element').data('config', { theme: 'dark', lang: 'en' });
// Get data
const userId = $('#element').data('userId'); // 123
const config = $('#element').data('config'); // { theme: 'dark', lang: 'en' }
// Get all data
const allData = $('#element').data();
// { userId: 123, config: { theme: 'dark', lang: 'en' } }
// HTML5 data attributes are auto-loaded
// <div id="user" data-user-id="456" data-role="admin">
$('#user').data('userId'); // 456
$('#user').data('role'); // 'admin'
.removeData(key)
Remove stored data.
$('#element').data('temp', 'value');
$('#element').removeData('temp');
// Remove all data
$('#element').removeData();
Traversal
.find(selector)
Find descendant elements.
// Find all paragraphs inside #content
$('#content').find('p').addClass('styled');
// Chained traversal
$('#nav')
.find('li')
.find('a')
.addClass('nav-link');
.filter(selector) / .filter(function)
Reduce matched elements.
// Filter by selector
$('li').filter('.active').css('font-weight', 'bold');
// Filter by function
$('input').filter(function() {
return $(this).val().length > 0;
}).addClass('has-value');
// Filter with index
$('tr').filter(':even').addClass('striped');
.closest(selector)
Find closest ancestor matching selector.
// Find parent form
$('input').on('blur', function() {
const $form = $(this).closest('form');
validateForm($form);
});
// With context
$('.item').closest('.container', '#wrapper');
.has(selector)
Filter elements that have matching descendants.
// Only select divs that contain a span
$('div').has('span').addClass('has-span');
// Select list items with links
$('li').has('a').css('background', '#f0f0f0');
.index([selector | element])
Get element index.
// Index among siblings
$('li.active').index(); // Position among siblings
// Index in jQuery collection
const $items = $('li');
$items.index($('.active')); // Position in collection
// With selector
$('li').index('li.active'); // Find index of .active among all li
.add(selector)
Add elements to the matched set.
// Combine selections
$('p')
.add('span')
.add('div.highlight')
.addClass('styled');
// Add newly created element
$('.existing').add('<p>New paragraph</p>').appendTo('#container');
.addBack([selector])
Add previous set to current set.
// Select all children and the parent
$('#parent')
.find('> *')
.addBack()
.addClass('highlighted');
// With filter
$('ul')
.find('li')
.addBack('ul.main')
.css('border', '1px solid');
DOM Evaluation
jQuery.DOMEval(code, options)
Safely execute script code with nonce support (internal use, enhanced in 4.0).
// jQuery internally uses this for script execution
// Preserves nonce attributes for CSP compliance
// Handles type, src, nonce, and noModule attributes
Security Features
Prototype Pollution Prevention
jQuery 4.0 includes protection against prototype pollution attacks in $.extend():
// These attempts are blocked
$.extend(true, {}, JSON.parse('{"__proto__": {"polluted": true}}'));
$.extend(true, {}, { constructor: { prototype: { polluted: true } } });
// Object.prototype remains unpolluted
console.log({}.polluted); // undefined
XSS Mitigation
The selector engine escapes special characters to prevent XSS:
// Safe selector escaping
const userInput = 'div"><script>alert("xss")</script>';
const escaped = $.escapeSelector(userInput);
// Safely escaped for use in selectors
CSP Compliance
Script loading now complies with Content Security Policy:
// Scripts are loaded via <script> tags, not eval()
$.getScript('/trusted/script.js');
// Works with strict CSP headers:
// Content-Security-Policy: script-src 'self'
Changelog Summary
Added
- ES module support for modern build tools
- Trusted Types support for enhanced security
- CSP-compliant script loading
- Improved slim build (8kb smaller)
Removed
- IE 10 and earlier support
- Edge Legacy support
jQuery.isArray(),jQuery.parseJSON(),jQuery.trim(),jQuery.type()jQuery.now(),jQuery.isNumeric(),jQuery.isFunction(),jQuery.isWindow()push,sort,splicefrom jQuery prototype
Changed
- Focus event order now follows W3C specification
- Source migrated from AMD to ES modules
Resources
- Official Website: jquery.com
- Documentation: api.jquery.com
- GitHub: github.com/jquery/jquery
- npm: npmjs.com/package/jquery
- CDN: code.jquery.com
- Migration Plugin: github.com/jquery/jquery-migrate
Documentation generated for jQuery 4.0.0 (January 2026)