ES6(a.k.a ES2015) has been around for some time. Although it is fully backward compatible with previous version of JavaScript - ES5 which has been around for decades, there’s quite some new syntax and features introduced in ES6 that is exciting on one hand, but can easily get wrong on the other hand. This posts is my study notes on ES6.
let for block scoping
let
defines block scope variables, which can be accessed in a nested scope just like var
. The following code outputs 12
:
Unlike var
, let
is block scoped.
In the following example, every time the for loop runs, a new i
is declared. Thurs each function gets its own copy of i
.
The code outputs 0
:
Whereas in the following example, var i
is function scoped and hoisted. Each function gets the same i
. So the code outputs 2
An arrow function is not a function
It is not like a function
in a few ways. The key difference to note is that this
in an arrow function is
captured at function creation, not function invocation(runtime), and this
can’t be changed at runtime.
Unlike traditional function
, an arrow function is not ‘bindable’.
The following code outputs 123
rather than 456
:
Unlike function
, an arrow function is not ‘callable’.
Same as above, the following code outputs 123
rather than 456
:
Unlike function
, an arrow function doesn’t has a prototype
.
The code below outputs false
:
Default Parameters
Default parameters have access to any variables in the scope.
In the following example, price
and baseTax
can be accessed when defining another default parameter price
:
Default parameter doesn’t count as the actual parameter passed in.
The following code outputs 1
instead of 2
:
Default parameters have orders and are not hoisted.
The following example causes a SyntaxError
because adjustment
is used before it is defined:
However the following similar example is valid and outputs 6
. This is because JavaScript
is a dynamic language that doesn’t do compile time check, and at run time, the lookup for adjustment
is skipped when the actual parameter 5
is passed in and assigned to price
.
The Rest
Parameter
The concept is similar to Java’s Arbitrary Number of Arguments.
The ‘Rest’ parameter is always an array.
The following code outputs []
:
Unlike default parameters, the ‘Rest’ parameter doesn’t count as a parameter defined on the function signature.
The following code outputs 1
:
Just like default parameters, the ‘Rest’ parameter doesn’t count as a actual parameter passed in.
The following code outputs the number of actual parameters passed in, which is 3
The ‘Spread’ operator
...
is introduced in ES6 as the Spread
operator.
...
works not only with array, but with strings too.
The ...
breaks the string into a series individual characters, so the output is the maximum character 4
:
Object Literal Extensions
An object literal is a list of zero or more pairs of property names and associated values of an object, enclosed in curly braces {}
. In ES6, object
literals are extended with new features.
Like arrow functions, this
in a shorthand function refer to the context the function being called.
For example, the following code outputs 5.99
rather than 7.99
:
So we need to keep in mind that the shorthand functions are not exactly the same thing as the traditional functions. The same goes for arrow functions.
Template Literals
Expressions are allowed in ${}
ES6 Modules
Original reference to what is imported become unavailable once alias is used.
import
statements get hoisted
and executed first before any other code.
Suppose the following program starts from index.js
which loads module1.js
:
Named imports are read-only.
We can’t reassign a new value to named imports, but we can change properties.
ES6 modules export/import bindings/references rather than values.
In the example below, both primitive types: age
and name
get updated. So they are not
being imported as local variables:
Class
Unlike object literals, a class definition is ‘sort of’ like a function definition.
Because of that, ‘,’ causes SyntaxError
when running the following code:
But unlike a function, variables are not allowed to be declared inside a class. The following code also causes SyntaxError
:
Just like functions, class definitions can be used in expressions.
Please notice though, once class definition is assigned to a variable, the original reference is not available outside of the class definition.
Unlike functions, class definitions are not ‘callable’:
Unlike functions, class definitions are NOT polluting the global variable.
extends and super
The most basic form:
Default constructors for classes
When constructor is missing from base class, a default ‘non-parameterized’ one is created:
When constructor is missing from subclass, a default ‘parameterized’ one is created to make sure parameters can be passed onto super constructor.
While it is ok not to have an explicit call to super constructor super()
in base class, it is not ok to omit super()
call in a subclass.
So long as there’s a constructor in the subclass, a default constructor with super() call won’t be created.
this
ordering
In a subclass, you must call super()
before you can use this:
static function are to be called by class, not the instances.
new.target
is always pointing the initial class
new.target
can be used to access static functions defined in the original class:
Symbols
Symbol()
are creating new unique ones, even with same parameters.
Symbol.for()
on the other hand, only creates a new one when no existing one can be found
in the symbol registry.
Object properties created by Symbol are special ones that needs to be accessed in a special way: