ECMAScript 5 Compatibility Shims
es5-shim and es5-sham are JavaScript libraries designed to provide ECMAScript 5 (ES5) compatibility shims and polyfills for legacy JavaScript engines that lack native support for these features. The current stable version is 4.6.7, which was last published over four years ago (as of early 2022), indicating an extremely slow release cadence and placing the project firmly in maintenance mode, rather than active development. es5-shim.js faithfully emulates many ES5 methods like Array iteration methods, Date.now, and Function.prototype.bind, making them available in older environments. es5-sham.js, on the other hand, provides best-effort shims for features that cannot be fully or faithfully emulated (such as Object.create with property descriptors, Object.freeze, or Object.defineProperty). A key differentiator is its direct monkey-patching of the global JavaScript context, making it suitable for environments without modern transpilation or module bundling, particularly for ensuring compatibility in very old browser environments like Internet Explorer 8.
Common errors
-
Uncaught TypeError: Object.defineProperties called on non-object
cause Attempting to use `Object.defineProperties` (which `Object.create` with a second argument relies upon) or `Object.defineProperty` in a very old browser environment where `es5-sham` cannot fully emulate property descriptors.fixAvoid using the second argument of `Object.create` or `Object.defineProperty`/`Object.defineProperties` in targeted legacy environments with `es5-sham`. Some shams, like those for `Object.seal` or `Object.freeze`, will silently fail rather than throw an error, so do not rely on their immutability guarantees. -
Array.prototype.forEach is not a function
cause An ES5 method (like `forEach`) is being called on an array-like object in a legacy browser, but `es5-shim` was either not loaded, or not loaded early enough to patch `Array.prototype`.fixEnsure `es5-shim.js` is loaded as the very first script in your application, before any code that attempts to use ES5 `Array` methods. Verify the script path and loading order. -
Safari 11 throws on `.sort({})`cause An issue specific to Safari 11 (fixed in `4.5.10`) where `.sort({})` would throw an error, but `.sort(null)` would not.fixIf encountering `sort` related issues in Safari 11, upgrade `es5-shim` to version `4.5.10` or newer. This fix ensures the shimmed `sort` handles such cases gracefully.
Warnings
- breaking The `es5-shim` library is designed to monkey-patch native JavaScript objects. If other libraries or the host environment modify or replace native methods after `es5-shim` has run, conflicts or unexpected behavior can occur. Always load `es5-shim` and `es5-sham` as early as possible in your script execution stack.
- gotcha The `es5-sham.js` module provides 'best-effort' shims for features that cannot be fully emulated to spec in older environments, such as `Object.create`, `Object.defineProperty`, `Object.freeze`, `Object.seal`, and `Object.preventExtensions`. These shams might silently fail, return `undefined`, or not fully conform to the ES5 specification (especially regarding property descriptors or object immutability). Relying on the full spec-compliance of these particular shams in legacy engines is dangerous and often leads to subtle bugs.
- gotcha The `Function.prototype.bind` shim has known caveats. The bound function's `prototype` property is not fully spec-compliant, and its `arguments` and `caller` properties are not as protected as in native implementations. Additionally, bound functions might not strictly enforce `call`/`apply` checks to prevent execution as a constructor.
- breaking Version `4.5.11` of `es5-shim` was released with missing minified files. If you use `4.5.x` versions and rely on minified assets, this specific version will cause issues.
- gotcha The package is primarily intended for *legacy* JavaScript engines (e.g., Internet Explorer 8 and older browsers or old Node.js versions). Using `es5-shim` in modern environments that natively support ES5 and newer standards is unnecessary. It might introduce slight performance overhead or, in rare cases, unexpected behavior if specific shims conflict with or are less optimized than modern native implementations.
Install
-
npm install es5-shim -
yarn add es5-shim -
pnpm add es5-shim
Imports
- es5-shim.js
import 'es5-shim/es5-shim';
require('es5-shim/es5-shim'); - es5-sham.js
import 'es5-shim/es5-sham';
require('es5-shim/es5-sham'); - Full global patching (browser)
<script src="path/to/es5-shim.min.js"></script> <script src="path/to/es5-sham.min.js"></script>
Quickstart
const isArraySupported = typeof Array.isArray === 'function';
console.log(`Array.isArray supported before shim: ${isArraySupported}`);
// Load the es5-shim to polyfill standard ES5 features
require('es5-shim/es5-shim');
// Load the es5-sham for best-effort shims of unfaithful ES5 features
require('es5-shim/es5-sham');
const isArraySupportedAfterShim = typeof Array.isArray === 'function';
console.log(`Array.isArray supported after shim: ${isArraySupportedAfterShim}`);
const arr = [1, 2, 3];
const obj = { a: 1 };
console.log(`Array.isArray([1,2,3]): ${Array.isArray(arr)}`);
console.log(`Array.isArray({a:1}): ${Array.isArray(obj)}`);
// Demonstrate an Object.keys shim
const keys = Object.keys(obj);
console.log(`Object.keys({a:1}): ${JSON.stringify(keys)}`);
// Demonstrate Function.prototype.bind
const unboundFn = function(a, b) { return this.value + a + b; };
const boundFn = unboundFn.bind({ value: 10 }, 5);
console.log(`Bound function result: ${boundFn(2)}`);