Transpile ES8 features to ES5
BabelJS - Transpiling ES2017 (ES8) Features to ES5
Section titled “BabelJS - Transpiling ES2017 (ES8) Features to ES5”ECMAScript 2017 (often referred to as ES8) introduced several valuable features to JavaScript. For projects needing to support older environments, BabelJS is essential for transpiling these features into ES5-compatible code. The primary tool for this is @babel/preset-env, often in conjunction with core-js for polyfills.
Key ES2017 features include:
- Async Functions (
async/await) - Object.values() / Object.entries()
- String padding (
padStart()/padEnd()) - Object.getOwnPropertyDescriptors()
- Trailing commas in function parameter lists and calls.
We’ll focus on some of these and how Babel handles them. Assume a Babel setup with @babel/preset-env and core-js for polyfills.
Babel Configuration for Polyfills
Section titled “Babel Configuration for Polyfills”For features that are new methods or objects (not just syntax), polyfills are needed. Update your babel.config.json:
{ "presets": [ [ "@babel/preset-env", { "useBuiltIns": "usage", "corejs": 3 } ] ]}And ensure core-js is installed:
npm install --save core-js1. Async Functions (async/await)
Section titled “1. Async Functions (async/await)”Async functions provide a cleaner way to work with asynchronous operations based on Promises, making asynchronous code look and behave a bit more like synchronous code.
ES2017 Code (example: async_example.js)
Section titled “ES2017 Code (example: async_example.js)”function resolveAfter2Seconds() { return new Promise(resolve => { setTimeout(() => { resolve('resolved'); }, 2000); });}
async function asyncCall() { console.log('calling'); const result = await resolveAfter2Seconds(); console.log(result); // Expected output: "resolved"}
asyncCall();@babel/preset-env (which includes @babel/plugin-transform-async-to-generator) transforms async functions into generator functions. This also requires regenerator-runtime (handled by core-js setup above or by @babel/plugin-transform-runtime).
Transpilation Command
Section titled “Transpilation Command”npx babel async_example.js --out-file async_example_es5.jsTranspiled ES5 Code (Simplified, with helpers)
Section titled “Transpiled ES5 Code (Simplified, with helpers)”// May include imports for core-js/regenerator-runtime at the top// import "core-js/modules/es.object.to-string.js";// import "core-js/modules/es.promise.js";// import "regenerator-runtime/runtime.js";
"use strict";
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { /* ... helper ... */ }
function _asyncToGenerator(fn) { /* ... helper ... */ }
function resolveAfter2Seconds() { return new Promise(function (resolve) { setTimeout(function () { resolve('resolved'); }, 2000); });}
function asyncCall() { return _asyncCall.apply(this, arguments);}
function _asyncCall() { _asyncCall = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee() { var result; return regeneratorRuntime.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: console.log('calling'); _context.next = 3; return resolveAfter2Seconds(); case 3: result = _context.sent; console.log(result); case 5: case "end": return _context.stop(); } } }, _callee); })); return _asyncCall.apply(this, arguments);}
asyncCall();The transpiled code uses generator functions and the regeneratorRuntime (provided by core-js or @babel/runtime) to mimic async/await behavior. Promises also need to be polyfilled if not available.
2. String Padding (padStart() / padEnd())
Section titled “2. String Padding (padStart() / padEnd())”These methods pad the current string with another string (repeatedly, if needed) so that the resulting string reaches a given length. Padding is applied from the start (padStart) or end (padEnd) of the original string.
ES2017 Code (example: string_padding.js)
Section titled “ES2017 Code (example: string_padding.js)”const str = 'abc';
console.log(str.padStart(5, '_')); // Output: "__abc"console.log(str.padStart(2, '_')); // Output: "abc" (length already >= 2)console.log(str.padEnd(8, '*_')); // Output: "abc*_*_*"console.log('test'.padStart(10)); // Output: " test" (pads with spaces by default)These are new methods on String.prototype. Babel itself doesn’t transpile the methods, but with "useBuiltIns": "usage" and core-js, it will ensure polyfills for String.prototype.padStart and String.prototype.padEnd are included if your target environments need them.
Transpilation Command
Section titled “Transpilation Command”npx babel string_padding.js --out-file string_padding_es5.jsTranspiled ES5 Code (string_padding_es5.js)
Section titled “Transpiled ES5 Code (string_padding_es5.js)”// May include imports for core-js string padding modules at the top// e.g., import "core-js/modules/es.string.pad-start.js";// e.g., import "core-js/modules/es.string.pad-end.js";
"use strict";
var str = 'abc';console.log(str.padStart(5, '_'));console.log(str.padStart(2, '_'));console.log(str.padEnd(8, '*_'));console.log('test'.padStart(10));The syntax of the calls remains the same. The functionality is provided by the polyfills imported by Babel (due to useBuiltIns: 'usage').
Testing String Padding in a Browser
Section titled “Testing String Padding in a Browser”To test this in a browser, especially an older one, you would bundle string_padding_es5.js (which now includes core-js imports if generated by a bundler-aware Babel setup, or you ensure polyfills are loaded globally).
Create test.html:
<!DOCTYPE html><html><head> <title>BabelJS ES2017 String Padding Test</title></head><body> <p>Check the console for output.</p> <!-- Assuming string_padding_es5.js is bundled or polyfills are globally available --> <script src="path/to/your/bundled/string_padding_es5.js"></script></body></html>When opened in any browser (modern or older with polyfills), the console should show:
__abcabcabc*_*_* test3. Object.values() and Object.entries()
Section titled “3. Object.values() and Object.entries()”Object.values() returns an array of a given object’s own enumerable property values. Object.entries() returns an array of a given object’s own enumerable string-keyed property [key, value] pairs.
ES2017 Code (example: object_methods.js)
Section titled “ES2017 Code (example: object_methods.js)”const obj = { a: 1, b: 'hello', c: true };
console.log(Object.values(obj)); // Output: [1, "hello", true]console.log(Object.entries(obj)); // Output: [["a", 1], ["b", "hello"], ["c", true]]Similar to string padding, these are new static methods on Object. Babel with core-js will polyfill them.
Transpiled ES5 Code (object_methods_es5.js)
Section titled “Transpiled ES5 Code (object_methods_es5.js)”// May include imports for core-js Object.values/entries modules// e.g., import "core-js/modules/es.object.values.js";// e.g., import "core-js/modules/es.object.entries.js";
"use strict";
var obj = { a: 1, b: 'hello', c: true};console.log(Object.values(obj));console.log(Object.entries(obj));The calls to Object.values() and Object.entries() will work in older environments due to the polyfills provided by core-js.
Babel’s strength lies in its extensibility through presets and plugins, combined with polyfill solutions like core-js. This allows developers to confidently use modern JavaScript features like those from ES2017, knowing their code can be transformed to run reliably across a wide range of target environments.