a) New syntax is not recognized in older browsers. b) Some of the new features in the specification aren’t even implemented in any stable browsers yet.
So, what do you do with the new stuffs? Do you just have to wait around for years for all the old browsers to fade away & be patience for browser vendors to implement the new features. Well it’s not a good idea right?
The word “Polyfill” is an invented term (by Remy Sharp) used to refer talking the definition of a newer feature and producing a piece of code that’s equivalent to the behavior, but is able to run in older JS environments.
For example, ES6 defines a utility called
Number.isNaN(..) to provide accurate, non-buggy check for
NaN values, deprecating the original
isNaN(..) utility. But it’s easy to polyfill that utility so that you can start using it in your code regardless of whether the end user is an ES6 browser or not.
1 2 3 4 5
if statement guards against applying the polyfill definition in ES6 browsers where it will already exist. If it’s not already present, we define
Note: The check we do here takes advantage of a quirk with
NaN values, which is that they’re the only value in the whole language that is not equal to itself. So the
NaN value is the only one that would make
x !== x be
Not all new features are fully polyfillable. Sometimes most of the behavior can be polyfilled, but there are still small deviations. You should be really, really careful in implementing a polyfill yourself, to make sure you are adhering to the specification as strictly as possible.
There’s no way to polyfill new syntax that has been added to the language. The new syntax would throw an error in the old JS engine as unrecognized/invalid.
So the better option is to use a tool that converts your newer code into older code equivalents. This process is commonly called “transpiling,” a term for transforming + compiling.
Essentially, your source code is authored in the new syntax form, but what you deploy to the browser is the transpiled code in old syntax form. You typically insert the transpiler into your build process, similar to your code linter or your minifier.
You might wonder why you’d go to the trouble to write new syntax only to have it transpiled away to older code – why not just write the older code directly?
Here’s a quick example of transpiling. ES6 adds a feature called “default parameter values.” It looks like this:
1 2 3 4 5 6
Simple, right? Helpful, too! But it’s new syntax that’s invalid in pre-ES6 engines. So what will a transpiler do with that code to make it run in older environments?
1 2 3 4
As you can see, it checks to see if the
arguments value is
void 0 (aka
undefined), and if so provides the
2 default value; otherwise, it assigns whatever was passed.
In addition to being able to now use the nicer syntax even in older browsers, looking at the transpiled code actually explains the intended behavior more clearly.
You may not have realized just from looking at the ES6 version that
undefined is the only value that can’t get explicitly passed in for a default-value parameter, but the transpiled code makes that much more clear.
The last important detail to emphasize about transpilers is that they should now be thought of as a standard part of the JS development ecosystem and process. JS is going to continue to evolve, much more quickly than before, so every few months new syntax and new features will be added.
If you use a transpiler by default, you’ll always be able to make that switch to newer syntax whenever you find it useful, rather than always waiting for years for today’s browsers to phase out.
There are quite a few great transpilers for you to choose from. Here are some good options at the time of this writing: