ES6 to ES5 converter — arrow functions, let/const and template literals

Paste modern JavaScript and the common ES2015 syntax is rewritten as ES5, while anything it cannot convert safely, such as classes or destructuring, is listed with its line number.

Live demo · real result from this tool
Quotes

ES5 code

var greet = function (name) { if (name === void 0) { name = 'friend'; } return "Hello, " + name + "!"; };var items = [1, 2, 3].map(function (n) { return n * 2; });var user = { name: 'Asha', items: items, describe: function () { return this.name + " has " + items.length + " items"; } };

Converted

FeatureCount
const → var2
arrow functions2
default parameters1
template literals2
let → var1
shorthand properties1
method shorthand1

const becomes var, so reassignment is no longer prevented.

Processed on your device — nothing is uploaded.

How to use the ES6 to ES5 converter

  1. Paste your code into the JavaScript box.
  2. Pick the Quotes style, Double or Single, for strings the tool creates from template literals.
  3. Copy the ES5 code or download script.es5.js.
  4. Read the Converted table to see what changed, and any warning that starts “Not converted” to see what still needs work.

What it does and when to use it

Some places still run only ES5: old smart TVs and set-top boxes, embedded web views, legacy intranet browsers and a few scripting hosts. When you need one small function to run there, a full build setup is overkill. This tool rewrites the syntax with fixed rules and tells you honestly what it skipped.

Check the input first with the JavaScript validator, since the converter needs code that parses. To handle only template literals, the template literal to concat converter is lighter, and var to let / const goes the opposite way. Tidy the output with the JavaScript formatter.

How it works

The code is parsed with the Babel parser into a syntax tree. The tool then regenerates only the nodes it converts and copies everything else from your source, so comments and layout outside those spots stay as they were.

ES2015+ ES5 output
x => x * 2 function (x) { return x * 2; }
arrow using this (function () { … }).bind(this)
let / const var
`a${b}c` "a" + b + "c"
function f(b = 2) function f(b) { if (b === void 0) { b = 2; } … }
(...nums) => var nums = Array.prototype.slice.call(arguments, 0);
{ x, m() {} } { x: x, m: function () {} }

Worked examples

Default parameter and template literal.

const greet = (name = 'friend') => `Hello, ${name}!`;

becomes:

var greet = function (name) { if (name === void 0) { name = 'friend'; } return "Hello, " + name + "!"; };

Syntax it will not convert.

class Cart { add(...items) { return [...items]; } }
const { a, b } = obj;
const total = price ?? 0;

Only const changes. The warning lists class declarations, rest in destructuring and spread on line 1, object destructuring on line 2 and nullish coalescing on line 3. Line 2 comes out as var { a: a, b: b } = obj;, which is still not ES5, so fix flagged lines yourself.

A loop closure. for (let i = 0; i < 3; i++) { setTimeout(() => log(i)); } becomes for (var i = 0; i < 3; i++) { setTimeout(function () { return log(i); }); }. The tool warns because with var every callback sees the final i, so this logs 3 three times instead of 0, 1, 2. Wrap the body in a function that takes i as a parameter.

Limits and tips

  • Arrows that use arguments get a warning, because arguments now means the new function’s own arguments.
  • No polyfills and no module bundling. Remove import and export yourself or use a bundler.
  • Test the output in the target browser; syntax conversion cannot catch missing built-in methods.

Frequently asked questions

Is this a replacement for Babel?
No. It handles the most common syntax in small snippets, such as a script for an old embedded browser or a code sample. For a real project, use Babel or esbuild with a target setting, which convert everything and add the polyfills you need.
Why does my class stay as it is?
Classes, destructuring, spread, for…of, async/await, generators, optional chaining, the ?? and ** operators, computed keys and import/export need helper code or deeper rewrites. The tool leaves them unchanged and names each one with its line, so nothing is silently half-converted.
Does it add polyfills for Promise, Array.from or fetch?
No. It changes syntax only. Built-in objects and methods added after ES5 still need a polyfill in old browsers.
What does .bind(this) in the output mean?
An arrow function uses the this of the code around it. A plain function does not, so when the arrow body uses this, the tool adds .bind(this) to keep the same value.
Why does const become var?
ES5 has only var. The tool warns that reassignment is no longer blocked, and that var is shared by every closure created in a loop.

Written by the ToolsRift team · Last updated

Pages are drafted with AI assistance and checked by automated tests. How we write and check pages.

Was this tool useful?

Report a problem

Start typing to search every tool.

↑ ↓ to moveEnter to openEsc to close