- JavaScript is the common/generic name of the language.
- EcmaScript refers to the language’s specification.
- ES6 refers to the 6th edition of that spec.
- EcmaScript 2015 is the title of the 6th edition of the spec.
- EcmaScript refers to the language’s specification.
- Yes, we know this is ridiculous, but you will most certainly run across all of these on the web.
- For the purpose of this workshop, we will use JavaScript as much as possible, and ES6 when we are referring to a language feature that was added in the latest version of the spec only because it has fewer syllables when pronounced."
- All examples in this workshop assume strict mode. Incorporating Babel into your workflow will take care of this for you. All ES6 modules are in strict mode by default.
-
unlike languages with block level scope, in JavaScript blocks do not create their own restricted scope
function foo () { for (var i = 0; i < 10; i++) { } console.log(i); // 10 }
-
Here,
i
is available anywhere withinfoo
-
In the past, was often recommended that
var
statements occur at the beginning of functions to avoid unwelcome surprises caused by this behaviour- With ES6,
var
can largely be replaced bylet
- With ES6,
-
The
let
keyword restricts scope to its block, statement or expression:function bar () { for (let i = 0; i < 10; i++) { } console.log(i); // undefined }
-
const
creates a reference to a value that cannot be altered:function wombat () { const n = 5; n++; // TypeError: assignment to constant variable }
-
Functions can be declared inside other functions
-
local variables in the outer function are still available even if the outer function has already returned
function foo() { let n = 1; return bar; function bar() { // bar "closes over" n console.log(n++); } } let baz = foo(); baz(); // 1 baz(); // 2 baz(); // 3 let wombat = foo(); wombat(); // 1 baz(); // 4
- Here,
n
remains "alive" and can be modified afterfoo
exits. - Each call to
foo
creates a new closure, with its own local copy ofn
. - https://jsbin.com/cibibe/1/edit?js,console
- Here,
-
In ES6 the value of
this
is fairly predictable- Watch out for legacy JS, where it can unexpectedly default to the window object and lead to some unintuitive behaviour
- Best practice is to be explicit: never assume that the next developer to read your code understands the nuances of
this
- Think functionally: avoid altering global or object level state
-
Value of
this
depends on the execution context:console.log(this); // Value of 'this' already set to the Window object function foo () { console.log(this); // undefined } let bar = { wombat: function () { console.log(this); // Value of this is the object the method is called on } };
- In the last example,
this
is the objectbar
- In the last example,
-
this
can be tricky when used in event handlers. Generally its value is the DOM element which fired the event:<p id="foo">Aardvark.</p> <script> let foo = document.getElementById('foo'); foo.onclick = makeGreen; function makeGreen() { // 'this' is the <p> DOM element this.style.backgroundColor = 'green'; } </script>
- However, each function has its own
this
, which can lead to tricky situations with surrounding functions:
<p id="foo">Aardvark.</p> <script> let foo = document.getElementById('foo'); foo.onclick = toggleGreen; function toggleGreen() { if (this.style.backgroundColor === 'green') { makeTransparent(); } else { makeGreen(); } function makeGreen() { // 'this' is undefined this.style.backgroundColor = 'green'; } function makeTransparent() { // 'this' is undefined this.style.backgroundColor = 'transparent'; } } </script>
- However, each function has its own
-
Use of
call
invokes a function with the desired value ofthis
:if (this.style.backgroundColor === 'green') { makeTransparent.call(this); }
-
In JavaScript every object has its own prototype
- Each prototype has its own prototype, and so on down the chain until
null
is reached - Properties are first looked for in the object itself (see:
hasOwnProperty
, then in its prototype, then in the prototype's prototype, and so on
- Each prototype has its own prototype, and so on down the chain until
-
It's useful to remember the difference between giving one distinct object a property:
let foo = { aardvarks: function() { console.log("I see many aardvarks."); } }; foo.aardvarks(); // I see many aardvarks
-
and giving all objects created with a particular constructor function access to the property:
function AardvarkCounter(n) { this.count = n; } AardvarkCounter.prototype.aardvarks = function() { console.log(`I see ${this.count} aardvarks.`); }; let firstCounter = new AardvarkCounter(11); let secondCounter = new AardvarkCounter(1337); firstCounter.aardvarks(); // "I see 11 aardvarks." secondCounter.aardvarks(); // "I see 1337 aardvarks."
-
Functions declared on the prototype are shared between all objects with that prototype
-
Many libraries include the ability to copy properties from one object to another
-
For example, using Underscore's
extend
:let foo = { n: 5 }; let bar = { wombat: function() { console.log("Wombats: accept no substitute."); } }; let combined = _.extend(foo, bar); combined.wombat(); console.log(combined.n); // 5
-
To make a property, function, or object available outside its own file (module), prefix it with the
export
keyword: _// wombats.js export const metabolism = 4; export function showWombats() { // ... };
-
To make use of this in another module, we use
import
. The following will all makeshowWombats
available:import wombats from './wombats'; // Import the entire module import {showWombats} from './wombats'; // Just one function import {showWombats as sw} from './wombats'; // Same as above, but give it a shorter alias
- In the first statement,
showWombats
would be referred to aswombats.showWombats
- https://gist.github.com/locksmithdon/96fb0ae2904f86c86e66
- In the first statement,
-
If you've ever wished that JavaScript had X feature from another language, chances are it (or something like it) is provided by a utility library
-
One of the key roles of a utility library is making it simpler, more expressive, and less error-prone to work with data structures (an array, object, or string).
-
Utility libraries act as extensions to the JavaScript standard library, providing consistent and well-tested ways to interact with data structures.
-
The two most popular are Underscore and its API-compatible alternative, Lo-Dash
- The question of which one to use has gotten quite political, and beyond our scope here. Either one will run the examples.
-
Given an array:
let aardvarks = ["Snuffler", "Stinker", "Slappy", "Sadface"];
-
You could do this:
for (let i = 0; i < aardvarks.length; i++) { console.log(aardvarks[i]); }
-
Or this:
_.each(aardvarks, console.log);
-
Checking to see if an object has a particular property is another common use case:
let wombat = { registeredToVote: false, highlyOpinionated: true }; if (_.contains(_.keys(wombat), 'registeredToVote')) { console.log("Marsupial voter registration data exists for this entity."); }
-
Some standard library functions are duplicated in the utility libraries:
let foo = [1, 2, 3, 4, 5]; // Standard library let sum1 = foo.reduce( function (prev, curr) { return prev + curr; }); // Underscore / Lo-Dash let sum2 = _.reduce(foo, function (total, n) { return total + n; }); // Alternative syntax let sum3 = _(foo).reduce( function (total, n) { return total + n; }); console.log(sum1, sum2, sum3); // 15 15 15
-
Why not use the standard library version?
- Allows us to use the same approach whenever working with any data structures (objects, strings, and arrays), so we don't need to explicitly convert to array and back again. This can give our code consistency and readibility.
- In some circumstances, the library will default to the native version if it's known to be faster in a given environment.
- let - MDN
- const - MDN
- Closures - canonical Stack Overflow answer
- this - MDN
- all this
- JavaScript 'this' and event handlers
- call
- Inheritance and the prototype chain
- Promise - MDN
- The Long Road to Async/Await in JavaScript
- Lodash: 10 JavaScript Utility Functions That You Should Probably Stop Rewriting
- Learn ES2015
- Exploring ES6 (free online book)