ES6 - JavaScript Improved course lesson 4/4
Udacity Google Mobile Web Specialist Nanodegree program part 3 lesson 07
Udacity Grow with Google Scholarship challenge course lesson 09
Brendon Smith
This lesson will show us how to write ES6 code, even when browsers haven't caught up to the latest features yet.
ES6 is also referred to as ES2015.
The code from the course throws errors in old browsers like Safari 9 and IE 11
It makes sense that code doesn't work in older browsers that were developed prior to the release of ES6, but there are some browsers that have been released after ES6 that don't support the new JavaScript syntax and functionality yet.
Most of us don't think much about the browser and all it can do...until it doesn't work! But really, browser makers have a tough time. Think about HTML, CSS, and JavaScript - these languages are fluid and are always improving. Browser makers have to keep up with all of these changes.
They learn (or actually build) the language specifications!
Just like the World Wide Web Consortium (W3C) is the standards body for things like HTML, CSS, and SVG, Ecma International is an industry association that develops and oversees standards like JavaScript and JSON. You can find the specifications for ES6 here.
Ecma International is an important industry community and definitely worth checking out in more detail:
- https://en.wikipedia.org/wiki/Ecma_International
- http://www.ecma-international.org/memento/index.html
NOTE: The code we've been looking at in this course is not supported by older browsers. Older browsers that were developed prior to the release of ES6 were developed to support the version of JavaScript at the time (which was ES5.1). If you try running any ES6 code in an older browser, it won't work.
The specification (commonly shortened to "spec") for ES6 can be found here. The spec lists the set of rules and guidelines on how the language is supposed to function. It doesn't give specific details on how browser makers are supposed to achieve functionality, but it does provide step-by-step instructions on how the language is supposed to work. While making this course, we repeatedly referred to this official spec.
Ok, so honestly, it can be a little difficult to decipher some of the cryptic wording of the spec. But when you have a question about ES6, we recommend checking out info on the topic like that provided by the Mozilla Developer Network and then also reviewing what the spec actually says.
Check out the ES6 Specification. Which section in the spec covers arrow functions?
- section 6
- section 10.3.2
- section 14.2
- section 18.3.29
Solution
section 14.2
With new language specifications coming out every year and with browsers updating every other month, it can be quite challenging to know what browser supports which language features. Each browser maker (except for Safari) has a website that tracks its development status. Checkout the platform feature updates for each browser:
- Google Chrome - https://www.chromestatus.com/features#ES6
- Microsoft Edge - https://developer.microsoft.com/en-us/microsoft-edge/platform/status/?q=ES6
- Mozilla Firefox - https://platform-status.mozilla.org/
NOTE: Safari doesn't have its own platform status website. Under the hood, though, Safari is powered by the open source browser engine, Webkit. The status for Webkit features can be found here.
This can be a lot of information to track down. If you prefer a birdseye view of all the feature support for all JavaScript code, check out
You can also use the ECMAScript Compatibility Table built by @kangax:
Looking at the ECMAScript Compatibility Table, what kind of information does the first colored column display?
- The list of up-to-date browsers that support ES6.
- The list of all ES6 features.
- The status of all ES6 features supported by your current browser.
- Links to each browser platform's status for the specific ES6 feature.
Solution
The status of all ES6 features supported by your current browser.
The very first column lists all of the ES6 features. The second column in the table is the first one that's colored and displays the support of each ES6 feature in your the current browser.
As developers, we need to always be learning and adapting as the web does.
Richard and James use the analogy of filling a hole in the wall with spackling (UK brand name is Polyfilla).
In JavaScript, a polyfill is:
a JavaScript file that patches a hole by replicating some native feature that's missing.
A polyfill, or polyfiller, is a piece of code (or plugin) that provides the technology that you, the developer, expect the browser to provide natively.
Coined by Remy Sharp - https://remysharp.com/2010/10/08/what-is-a-polyfill
We, as developers, should be able to develop with the HTML5 APIs, and scripts can create the methods and objects that should exist. Developing in this future-proof way means as users upgrade, your code doesn't have to change but users will move to the better, native experience cleanly. From the HTML5 Boilerplate team on polyfills - https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-Browser-Polyfills
The code below is a polyfill for the new ES6 String method, startsWith():
if (!String.prototype.startsWith) {
String.prototype.startsWith = function(searchString, position) {
position = position || 0
return this.substr(position, searchString.length) === searchString
}
}
As you can see, a polyfill is just regular JavaScript.
This code is a simple polyfill (check it out on MDN), but there's also a significantly more robust one, here
Why does the startsWith()
polyfill begin with the following line?:
if (!String.prototype.startsWith)
- Without it, the script would throw an error.
- It checks to make sure the
String.prototype
exists. - It avoids overwriting the native
startsWith
method.
Solution
It avoids overwriting the native startsWith
method.
I thought it would just check for startsWith
, but didn't realize that overwriting would be a concern.
Remember that a polyfill is used to patch missing functionality. If the browser supports ES6 and has the native startsWith method, then there's no reason to polyfill it. If this check didn't exist, then this polyfill would overwrite the native implementation.
Remember that a polyfill is used to fill a hole in a browser that doesn't yet support the native feature.
This polyfill starts with a check to see if the native
startsWith
method actually exists. If it does exist then we don't want to override the native version with this one. If it doesn't exist then the browser will then run the code following.if (!String.prototype.startsWith) { String.prototype.startsWith = function(searchString, position) { position = position || 0 return this.substr(position, searchString.length) === searchString } } ;/- Sample usage */ "Udacity".startsWith("Udac") // returns `true` "Udacity".startsWith("Udac", 2) // returns `false` "Udacity".startsWith("ES6") // returns `false`This adds a new method to String's prototype object. The function defaults to the position indicated by this second argument that's passed in or it'll be the first character of the string.
Then it returns
true
orfalse
if the string that's passed in is the same as the string that we're looking at.
JavaScript is the language used to create a polyfill, but a polyfill doesn't just patch up missing JavaScript features! There are polyfills for all sorts of browser features:
- SVG
- Canvas
- Web Storage (local storage / session storage)
- Video
- HTML5 elements
- Accessibility
- Web Sockets
- and many more!
For a more-complete list of polyfills, check out this link
- Compiling: source code -> machine code. Reduces abstraction.
- Transpiling: source code -> another source code at the same level of abstraction.
Quiz
To convert Java to JavaScript, would you use a compiler or a transpiler?
Solution
First try
Transpiler
Since both the Java source code and the JavaScript target code are of the same level of abstraction (they're both human-readable), a transpiler would be used.
The most popular JavaScript transpiler is called Babel.
Babel's original name was slightly more descriptive - 6to5. This was because, originally, Babel converted ES6 code to ES5 code. Now, Babel does a lot more. It'll convert ES6 to ES5, JSX to JavaScript, and Flow to JavaScript.
Before we look at transpiling code on our computer, let's do a quick test by transpiling some ES6 code into ES5 code directly on the Babel website. Check out Babel's REPL(Read-Eval-Print Loop) and paste the following code into the section on the left:
class Student {
constructor(name, major) {
this.name = name
this.major = major
}
displayInfo() {
console.log(`${this.name} is a ${this.major} student.`)
}
}
const richard = new Student("Richard", "Music")
const james = new Student("James", "Electrical Engineering")
If you check in the repo for this project, inside the Lesson 4 directory is a little project that's all set up for transpiling ES6 code to ES5 code. There's an "ES6" directory that contains the ES6 code we'll be transpiling (using Babel) to ES5 code that will be able to run in every browser.
The way Babel transforms code from one language to another is through plugins. There are plugins that transform ES6 arrow functions to regular ES5 functions (the ES2015 arrow function plugin). There are plugins that transform ES6 template literals to regular string concatenation (the ES2015 template literals transform). For a full list, check out all of Babel's plugins.
Now, you're busy and you don't want to have to sift through a big long list of plugins to see which ones you need to convert your code from ES6 to ES5. So instead of having to use a bunch of individual plugins, Babel has presets which are groups of plugins bundled together. So instead of worrying about which plugins you need to install, we'll just use the ES2015 preset that is a collection of all the plugins we'll need to convert all of our ES6 code to ES5.
You can see that the project has a
.babelrc
file. This is where you'd put all of the plugins and/or presets that the project will use. Since we want to convert all ES6 code, we've set it up so that it has the ES2015 preset.
{
"presets": ["es2015"]
}
WARNING: Babel uses both Node and NPM to distribute its plugins. So before you can install anything, make sure you have both of these tools installed:
- install Node (which will automatically install NPM)
Note that Richard has selected the MIT license for his materials. I have correspondingly also selected the MIT license for my course repo.
The project's *package.json- file lists all of the NPM packages that this project depends on.
This project depends on
babel-cli
babel-preset-es2015
The babel 2015 preset is a collection of all es6 plugins. So these are the plugins that will be downloaded and installed.
Once they're installed we need to tell the Babel CLI which plugins it should use to do the transpiling. The CLI will check the *.babelrc- file for which plugins and presets to use.
So the _package.json- file lists what should be installed and the _.babelrc- file tells babel which plugins to use when it does its transpiling.
Now that babel knows to use this preset we need to tell it to actually transpile the code. To do that we've added a build script that will tell babel to take the files in the ES6 directory, transpile them using the es2015 preset, and then put the transformed code in the ES5 directory.
NOTE: As of the creation of this course (circa Winter 2016), most of ES6 is supported by the current set of browsers. But that's "most", not "all", unfortunately. And that's also referring to "current" browsers. There are plenty of older browsers that do not support many, if any, of the new ES6 additions. However, it is safe to say that pretty much every browser supports the previous version of the language (ES5.1).
It's important to stay on top of all the changes JavaScript is going through. The best way to do that is to start making use of the new features that are added. The problem is that not all browsers support these new features.
So, to have your cake and eat it too, you can write in ES6 and then use a transpiler to convert it to ES5 code. This lets you transform your project's code base to the newest version of the language while still letting it run everywhere. Then, once all of the browsers your app has to run on fully support ES6 code, you can stop transpiling your code and just serve the straight ES6 code, directly!
Informative and helpful lesson.