var is function scoped, cons and let are block (lexical) scoped
property initializer shorthand
concise method names
computed property names
new Object methods
Object.is() - make up for the remaining quirks of the identically equals operator
Object.assign(receiver, suppliers) - copy properties from supplier into receiver
Object.getOwnPropertyNames() - return all properties of an object (as opposed to only enumerable for Object.keys())
de-structure a target objects' properties
works on all objects (including arrays)
can have default values for undefined properties
default values evaluation is similar to a list of let variables declaration
rest parameters for functions and rest items for arrays
use the ... operator to:
represent an indefinite number of function parameters as an array
to assign remaining values in an array to a particular value
allows an expression to be expanded in places where multiple arguments (for function calls) or multiple elements (for array literals) or multiple variables (for destructuring assignment) are expected
a replacement for apply
easier array operations
easier copy operation for arrays and objects
shorthand for the function expression
does not bind its own this, arguments, super or new.target
preserves the 'this' of the calling location
best suited for non-method functions
are always anonymous
cannot be used as constructors and do not have a prototype
does not bind to an arguments object -> use rest params
function() {
if(true) {
var x = 1;
}
console.log(x) // 1
}
Block level scoping: const and let
function() {
for(var i=0;i< 10;i++) {
var x = 1;
}
console.log(i) // 10
console.log(x) // 1
}
function() {
if(true) {
let x = 1;
}
console.log(x) // x doesn't exist here
}
function() {
let x = 1;
if(true) {
let x = 2; // error cannot reasign
}
}
function() {
const a; // error, need to initialize const
const b = 1;
b = 2; // error cannot reasign
}
function() {
for(var i=0; i<10; i++) {
let x = 1;
}
console.log(i, x) // i, x don't exist here
}
var firstName = "Andrei",
lastName = "Antal";
var fullName = "The full name is: " + firstName + " " + lastName
Template strings
var fullName = `The full name is: ${firstName} ${lastName}`;
function() {
return (new Date()).year;
}
var currentYear = `The cuurent Year is ${getYear()}`;
var theSum = `The sum is ${3 + 4 / 2}`;
const theString = upp`Hello ${firstName} ${lastName}!`;
function upp(literal, name, name2) {
return [
literal[0],
name,
literal[1],
name2.toUpperCase(),
literal[2],
].join("");
}
const name = "Andrei";
const age = 29;
const user1 = {
name: name,
age: age,
sayHello: function() {
console.log("Yo!");
}
}
Enhanced object literals
const user2 = {
name,
age,
sayHello() {
console.log("Yo!");
}
}
const firstName = "first name";
const suffix = " name";
const person = {
[firstName]: "Andrei",
["last" + suffix]: "Antal"
};
const obj1 = {
a: 'a',
b: 'b',
};
const obj2 = { b: 'c' };
Object.assign(obj1, obj2); // obj1 = { a: 'a', b: 'c' }
Object.assign({}, obj1, obj2); // { a: 'a', b: 'c' }
let options = {
repeat: true,
save: false
};
let repeat = options.repeat;
let save = options.save;
Destructuring
let {repeat, save} = options;
console.log(repeat); // true
console.log(save); // false
let {repeat: re, save: sa, stop: st = false} = options;
console.log(re, sa, st); // true, false, false
let [one, two, three] = [1,2,3];
console.log(one, two, three); // 1,2,3
let [, , three] = [1,2,3];
console.log(three); // 3
const animal = {
name: 'Dog',
sound: 'wof'
};
function makeSound(options) {
options.name = options.name || 'animal';
console.log(`The ${options.animal} goes ${options.sound}`)
}
Destructuring
function makeSound({name = 'animal', sound}) {
console.log(`The ${name} goes ${sound}`)
}
makeSound(animal);
function doSomething(a,b, ...rest) {
console.log(a);
console.log(b);
console.log(rest);
}
doSomething(1,2,3,4,5); // 1, 2, [3,4,5]
function doSomething(a,b, ...rest, c){} // error; rest must be the last in param list
Rest operator
const arr = [1, 2, 3, 4, 5];
const [,, ...arr1] = arr;
console.log(arr1); // [3, 4, 5]
function doSomething(a,b, ...[c,d,e]){
console.log(a);
console.log(b);
console.log(c,d,e);
}
doSomething(1,2,3,4,5);
function logNumbers(a, b, c) {
console.log(a)
console.log(b)
console.log(c)
}
const array = [1,2,3];
logNumbers(...array);
Spread
const array = [1,2,3];
console.log([...array, 4, 5]);
const obj1 = {a: 'a', b: 'b'};
const obj2 = {c: 'c', ...obj1};
console.log(obj2);
const arr1 = [1,2,3];
const arr2 = [2,3,4];
const arr3 = [...arr1, 8, ...arr2];
console.log(arr3);
const sum = (num1, num2) => { return num1 + num2 };
const sum = function(num1, num2) {
return num1 + num2;
};
Arrow functions
const square = value => value * value;
const square = function(value) {
return value * value;
};
const getName = () => "Andrei";
const getName = function() {
return "Andrei";
};
const getTempItem = (id) => ({ id: id, name: "Temp" });
const getTempItem = function(id) {
return {
id: id,
name: "Temp"
};
};
const sum = (num1, num2) => { return num1 + num2 };
const sum = function(num1, num2) {
return num1 + num2;
};
Arrow functions
const square = value => value * value;
const square = function(value) {
return value * value;
};
const getName = () => "Andrei";
const getName = function() {
return "Andrei";
};
const getTempItem = (id) => ({ id: id, name: "Temp" });
const getTempItem = function(id) {
return {
id: id,
name: "Temp"
};
};
syntactic sugar over over JavaScript's existing prototype-based inheritance - does not create a new object oriented inheritance model
classes are defined using the class keyword
class declarations are not hoisted
a primitive (value) data type whose instances are unique and immutable
for debugging purposes symbols can have an optional description - stored in the [[Description]] property
symbols do not have a literal form, so they do not coerce into other primitive types
mostly used to create private properties - symbol keys are not visible in iterations
ES6 provides a global symbol registry in order to share symbols across the app
extra data types for working with collections (besides the Array data type)
can store primitive or object values
Set - iterable list of objects that cannot contain duplicates; elements are set in the insertion order
Map - iterable key/value pair entries list - keys can be objects, symbols, primitives and functions
WeakMap, WeakSet - non enumerable versions where keys/entries are referenced weakly - can be garbage collected if they aren't referenced elswhere
generator - object is returned by a generator function and it conforms to both the iterable protocol and the iterator protocol.
declared by adding a "*" between function and the name
use the yield keyword to denote execution halt until the next() method is called
each yield return an iteration (value, done) object
proxy objects are used to define custom behavior for fundamental operations
create a proxy to use in place of another object (called the target)
intercept low-level object operations on the target (using a trap) that are otherwise internal to the JavaScript engine
use the Proxy constructor to make a proxy - pass it two arguments: the target and a handler (an object that defines one or more traps)
module system
native promises
tail call optimization