A glimpse at some common ES6 features.
Arrow Function
An arrow function expression has a shorter syntax than a function expression and does not have its own this, arguments, super, or new.target.
These function expressions are best suited for non-method functions, and they cannot be used as constructors.
Basic syntax(be aware of the last case):
1 | (param1, param2, …, paramN) => { statements } |
Comment:
Two factors influenced the introduction of arrow functions: shorter functions and non-binding of this.
See this example:1
2
3
4
5
6
7
8
9
10
11
12
13
14function Person() {
// The Person() constructor defines `this` as an instance of itself.
this.age = 0;
setInterval(function growUp() {
// In non-strict mode, the growUp() function defines `this`
// as the global object (because it's where growUp() is executed.),
// which is different from the `this`
// defined by the Person() constructor.
this.age++;
}, 1000);
}
var p = new Person();
Traditional (ES3, ES5) solutions:1
2
3
4
5
6
7
8
9
10function Person() {
var that = this;
that.age = 0;
setInterval(function growUp() {
// The callback refers to the `that` variable of which
// the value is the expected object.
that.age++;
}, 1000);
}
Or we could use bind()
function.
ES6 solution:
An arrow function does not have its own this; the this value of the enclosing execution context is used. Thus, in the following code, the this within the function that is passed to setInterval has the same value as this in the enclosing function:1
2
3
4
5
6
7
8
9function Person(){
this.age = 0;
setInterval(() => {
this.age++; // |this| properly refers to the Person object
}, 1000);
}
var p = new Person();
Addition:
- Arrow functions do not have a prototype property.
- The yield keyword may not be used in an arrow function’s body (except when permitted within functions further nested within it). As a consequence, arrow functions cannot be used as generators.
Class
JavaScript classes, introduced in ECMAScript 2015, are primarily syntactical sugar over JavaScript’s existing prototype-based inheritance. The class syntax does not introduce a new object-oriented inheritance model to JavaScript.
Define a class
Class Declaration:
1
2
3
4
5
6class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}
}Class expressions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19// unnamed
let Rectangle = class {
constructor(height, width) {
this.height = height;
this.width = width;
}
};
console.log(Rectangle.name);
// output: "Rectangle"
// named
let Rectangle = class Rectangle2 {
constructor(height, width) {
this.height = height;
this.width = width;
}
};
console.log(Rectangle.name);
// output: "Rectangle2"
Strict mode in Class
Code within the class syntax is always executed in strict mode, see this example:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17class Animal {
speak() {
return this;
}
static eat() {
return this;
}
}
let obj = new Animal();
obj.speak(); // Animal {}
let speak = obj.speak;
speak(); // undefined
Animal.eat() // class Animal
let eat = Animal.eat;
eat(); // undefined
What will happen in traditional mode?1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16function Animal() { }
Animal.prototype.speak = function() {
return this;
}
Animal.eat = function() {
return this;
}
let obj = new Animal();
let speak = obj.speak;
speak(); // global object
let eat = Animal.eat;
eat(); // global object
Explanation:
Autoboxing in method calls will happen in non–strict mode based on the initial this value. If the inital value is undefined, this will be set to the global object.
Autoboxing will not happen in strict mode, the this value remains as passed.
Sub classing with extends
Basic example:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(this.name + ' makes a noise.');
}
}
class Dog extends Animal {
constructor(name) {
super(name); // call the super class constructor and pass in the name parameter
}
speak() {
console.log(this.name + ' barks.');
}
}
let d = new Dog('Mitzie');
d.speak(); // Mitzie barks.
If there is a constructor present in subclass, it needs to first call super() before using “this”.
Addition:
The only purpose of extends is to create single-ancestor class taxonomies.
let and const
The let statement declares a block scope local variable, optionally initializing it to a value.1
2
3
4
5
6
7
8
9
10
11let x = 1;
if (x === 1) {
let x = 2;
console.log(x);
// expected output: 2
}
console.log(x);
// expected output: 1
let is an alternative to Javascript’s traditional scoping rules
let
allows you to declare variables that are limited in scope to the block, statement, or expression on which it is used. This is unlike the var
keyword, which defines a variable globally, or locally to an entire function regardless of block scope.
Constants are block-scoped, much like variables defined using the let statement. The value of a constant cannot change through re-assignment, and it can’t be redeclared.1
2
3
4
5
6
7
8
9
10
11
12const number = 42;
try {
number = 99;
} catch(err) {
console.log(err);
// expected output: TypeError: invalid assignment to const `number'
// Note - error messages will vary depending on browser
}
console.log(number);
// expected output: 42