What JavaScript APIs Are Deprecated and Which Modern Alternatives Should You Use?
This article outlines ten JavaScript APIs that have been deprecated or discouraged—such as document.execCommand, escape, XMLHttpRequest sync mode, and performance.timing—explaining why they’re problematic and providing modern, safer alternatives like the Clipboard API, fetch, PerformanceNavigationTiming, and standardized string methods.
JavaScript, as an evolving language, continuously updates its APIs. New, safer, more efficient APIs appear while older ones are deprecated due to security, performance, design flaws, or better replacements. Continuing to use deprecated APIs can cause compatibility issues, security vulnerabilities, and maintenance difficulties.
1. document.execCommand()
Why deprecated: It was the main way to implement rich‑text editing (bold, italic, copy, paste) but its behavior varies across browsers, it is hard to extend, and it poses security risks such as XSS. The W3C no longer recommends it and suggests modern alternatives.
Alternative:
Clipboard API ( navigator.clipboard ) : asynchronous copy and paste of text or data, more secure and modern.
Selection API : obtain and modify the user's current text selection or range.
Direct DOM manipulation : modern editor libraries (e.g., Quill, Slate.js, Draft.js) or custom logic manipulate the DOM directly.
// Not recommended
// document.execCommand('copy');
// Recommended (copy text)
async function copyTextToClipboard(text) {
try {
await navigator.clipboard.writeText(text);
console.log('Text copied to clipboard');
} catch (err) {
console.error('Failed to copy: ', err);
}
}2. escape() and unescape()
Why deprecated: These functions perform URL encoding/decoding but fail to handle non‑ASCII characters correctly and do not encode all characters that have special meaning in URLs (e.g., +, /, @).
Alternative:
encodeURIComponent() / decodeURIComponent() : encode and decode URL query‑string parameters, handling all necessary characters.
encodeURI() / decodeURI() : encode and decode an entire URI, leaving characters such as :, /, ;, ? unescaped as appropriate.
// Not recommended
// const encoded = escape("你好 world?query=1");
// console.log(encoded); // %u4F60%u597D%20world%3Fquery%3D1 (incorrect handling of non‑ASCII)
// Recommended
const queryParam = "你好 world";
const encodedParam = encodeURIComponent(queryParam);
console.log(encodedParam); // %E4%BD%A0%E5%A5%BD%20world
const fullUrl = `https://example.com/search?q=${encodedParam}`;
console.log(fullUrl); // https://example.com/search?q=%E4%BD%A0%E5%A5%BD%20world3. Synchronous XMLHttpRequest
Why not recommended: Setting the third argument async of XMLHttpRequest.open() to false makes a synchronous request, blocking the JavaScript main thread until completion, freezing the UI and providing a poor user experience. Modern development favors asynchronous operations.
Alternative:
Asynchronous XMLHttpRequest : default behavior, using callbacks or Promises.
fetch API : a modern, Promise‑based API offering a cleaner and more powerful way to make network requests.
// Strongly discouraged
// const xhr = new XMLHttpRequest();
// xhr.open('GET', '/api/data', false); // false = synchronous
// xhr.send();
// if (xhr.status === 200) {
// console.log(xhr.responseText); // blocks until response
// }
// Recommended (using fetch)
async function fetchData(url) {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json(); // or .text()
console.log(data);
} catch (error) {
console.error('Fetch error:', error);
}
}
fetchData('/api/data');4. String.prototype.substr()
Why deprecated: substr() extracts a substring based on a start index and length. It is marked as a legacy feature because its second argument (length) is inconsistent with substring and slice, which use an end index, leading to confusion.
Alternative:
String.prototype.substring(indexStart, indexEnd) : extracts characters from indexStart up to but not including indexEnd.
String.prototype.slice(beginIndex, endIndex) : similar to substring but accepts negative indices.
5. Event.keyCode , Event.which , Event.charCode
Why deprecated: These properties return numeric codes for keyboard events, but their values vary across browsers, operating systems, and keyboard layouts, causing compatibility problems.
Alternative:
Event.key : returns a string representing the physical key value (e.g., "a", "Enter", "ArrowUp") and offers better internationalization support.
Event.code : returns a string representing the physical key code (e.g., "KeyA", "Enter", "ArrowUp") independent of layout.
6. window.event (global event object)
Why not recommended: In old IE event models the event object was accessed via the global window.event. Modern browsers follow the W3C standard, passing the event object as the first argument to the handler. Relying on the global object breaks in non‑IE browsers and strict mode.
Alternative:
Use the event object passed to the event handler.
7. String.prototype.trimLeft() and String.prototype.trimRight()
Why deprecated: These methods remove whitespace from the start or end of a string. The ECMAScript standard renamed them to trimStart() and trimEnd() for better semantic consistency with methods like padStart() and padEnd(). The old names remain as aliases but the new names are preferred.
Alternative:
String.prototype.trimStart() String.prototype.trimEnd()8. Window.showModalDialog()
Why deprecated: It opens a modal dialog that blocks JavaScript execution in the parent window until the dialog closes. This blocking behavior conflicts with modern asynchronous, non‑blocking web applications, provides a poor user experience, and poses security risks. Major browsers have removed it.
Alternative:
HTML <dialog> element : a native modal dialog that can be opened with showModal().
Modal components from JavaScript libraries/frameworks (e.g., Bootstrap Modals, Material‑UI Dialogs).
Custom CSS/JavaScript implementations using position: fixed or absolute with an overlay.
9. navigator.plugins and navigator.mimeTypes
Why deprecated/not recommended: These APIs detect installed browser plugins (e.g., Flash, Java). With the deprecation of NPAPI plugins for security and performance reasons, their usefulness has greatly diminished. Modern web technologies (HTML5, CSS3, WebAssembly) replace most plugin functionality.
Alternative:
Usually no direct replacement is needed; use feature detection instead of plugin detection.
10. Performance.timing
Why deprecated: The performance.timing object provides timestamps of the page load process (e.g., navigationStart, domContentLoadedEventEnd). Although still available, it has been superseded by the more precise PerformanceNavigationTiming interface, which can be accessed via performance.getEntriesByType('navigation').
Alternative: performance.getEntriesByType('navigation'): returns an array of PerformanceNavigationTiming objects with high‑resolution timestamps.
// Old way (still works but not recommended)
const timing = window.performance.timing;
console.log(`DOM content loaded: ${timing.domContentLoadedEventEnd - timing.navigationStart}ms`);
// Recommended way
const navigationEntry = performance.getEntriesByType('navigation')[0];
if (navigationEntry) {
console.log(`DOM content loaded (new): ${navigationEntry.domContentLoadedEventEnd}ms from navigationStart`);
}Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
JavaScript
Provides JavaScript enthusiasts with tutorials and experience sharing on web front‑end technologies, including JavaScript, Node.js, Deno, Vue.js, React, Angular, HTML5, CSS3, and more.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
