JS
es6
Agenda
- ES6
- Async and await
WebStorm ES6
ES6 - what is new?
- let and const
- Strings and RegEx
- Templating
- Functions (default, rest, spread, constructor)
- Arrow functions
- Objects (literal, is, assign)
- Destructuring
- Symbols
- Sets and Maps
- Iterators
- Generators
- Classes (static, inheritance
- Promisses
- Other
ES6 - let and const
const a = 5;
let b = 10;
if (true) {
let a = 1;
let b = 2;
const c = 3;
console.log(a, b); // 1 2
console.log(c); // 3
}
console.log(a, b); // 5 10
console.log(c); // Error
ES6 - let and const
// каждый цикл имеет свою переменную i
for(let i = 0; i<10; i++) { /* … */ }
for(let i = 0; i<10; i++) { /* … */ }
alert( i ); // ошибка: глобальной i нет
ES6 - let and const
// каждый цикл имеет свою переменную i
for(let i = 0; i<10; i++) { /* … */ }
for(let i = 0; i<10; i++) { /* … */ }
alert( i ); // ошибка: глобальной i нет
ES6 - let and const
Переменные let:
- Видны только после объявления и только в текущем блоке.
- Нельзя переобъявлять (в том же блоке).
- При объявлении переменной в цикле for(let …) – она видна только в этом цикле. Причём каждой итерации соответствует своя переменная let.
Переменная const – это константа, в остальном – как let.
ES6 - let and const
Переменные let:
- Видны только после объявления и только в текущем блоке.
- Нельзя переобъявлять (в том же блоке).
- При объявлении переменной в цикле for(let …) – она видна только в этом цикле. Причём каждой итерации соответствует своя переменная let.
Переменная const – это константа, в остальном – как let.
ES6 - Destructuring
let obj = {
name: 'Ivan',
addresses: ['Addr 1', 'Addr 2'],
family: {
mother: {
name: 'Olha',
age: 60
}
}
};
let {
name,
addresses: where = 'Nowhere',
salary = 1000,
family: {
mother
}
} = obj;
console.log(name, where, salary, mother.name);
// Ivan [Addr 1, Addr 2] 1000 Olha
ES6 - Destructuring
Деструктуризация (destructuring assignment) – это особый синтаксис присваивания, при котором можно присвоить массив или объект сразу нескольким переменным, разбив его на части.
ES6 - spread
Если мы хотим получить и последующие значения массива, но не уверены в их числе – можно добавить ещё один параметр, который получит «всё остальное», при помощи оператора "..."(«spread», троеточие):
'use strict';
let [firstName, lastName, ...rest] = "Юлий Цезарь Император Рима".split(" ");
console.log(firstName); // Юлий
console.log(lastName); // Цезарь
console.log(rest); // Император,Рима (массив из 2х элементов)
ES6 - spread
Если мы хотим получить и последующие значения массива, но не уверены в их числе – можно добавить ещё один параметр, который получит «всё остальное», при помощи оператора "..."(«spread», троеточие):
ES6 - default value
'use strict';
let [firstName, lastName] = [];
console.log(firstName); // undefined
// значения по умолчанию
let [firstName="Гость", lastName="Анонимный"] = [];
alert(firstName); // Гость
alert(lastName); // Анонимный
ES6 - Strings and RegEx
-
UFT-18 support
-
normalize
-
/u flag in RegEx
-
includes(), startsWith(), endsWith()
-
repeat()
let s = 'Test';
if (s.startsWith('T')) {
console.log('Starts '.repeat(2));
} else {
console.log('Does not Start '.repeat(2));
// Does not Start Does not start
}
ES6 - Strings and Templating
console.log(`моя
многострочная
строка`);
let i = 1;
let message = `
Hello User-${i}.
Hello User-${++i}.
Hello User-${++i}!
`;
console.log(message); // Hello User1. Hello User-2. Hello User-3!
ES6 - Functions - Default values
function getValue(value) {
return value + 5;
}
function add(first = 0, second = getValue(first)) {
return first + second;
}
console.log(add()); // 5
console.log(add(1)); // 7
console.log(add(1, 1)); // 2
ES6 - Functions - Spread
function check(...args) {return args[0]; }
console.log(check(null)); //
console.log(check(1)); // 1
console.log(check(2, 4, 6)); // 2
console.log(check([1, 1], [2, 2], [3, 3])); // 1,1
let values= [1,2,3];
console.log(Math.max(...values)); // 3
console.log(Math.max(...values, 1)); // 3
console.log(Math.max(...values, 4)); // 4
ES6 - Spread vs Arguments
function check2(...spred) {
spred.forEach((item) => {
console.log(item)
})
}
check2(1,2,3) // 1,2,3
function check2(a, b, c) {
arguments.forEach((item) => {
console.log(item)
})
}
check2(1,2,3) // arguments.forEach is not a function
ES6 - Arrow Functions
let doNothing = () => {};
let sum = (num1, num2) => num1 + num2;
console.log(sum(1, 2)); // 3
let values = [5, 10, 0, 20];
console.log(values.sort((a, b) => a - b)); // 0,5,10,20
-
=> as return
-
no specific this
-
no specific arguments
ES6 - Arrow Functions
let group = {
title: "Наш курс",
students: ["Вася", "Петя", "Даша"],
showList: function() {
this.students.forEach(
student => alert(this.title + ': ' + student)
)
}
}
group.showList();
// Наш курс: Вася
// Наш курс: Петя
// Наш курс: Даша
Функции-стрелки не имеют своего this
ES6 - Objects
function CreatePerson(name, age) {
return { name, age, hello() { return `Hello ${this.name}`;} };
}
let person = new CreatePerson('Ivan', 30);
console.log(person.hello()); // Hello Ivan
// Object.is insead of ===
console.log(Object.is(5, 5)); // true
console.log(Object.is(5, "5")); // false
console.log( Object.is(+0, -0)); // false
console.log( +0 === -0 ); // true
console.log( Object.is(NaN, NaN) ); // true
console.log( NaN === NaN ); // false
// Object.assign
let receiver = {};
Object.assign(receiver, {
type: "js",
name: "file.js"
}, {
type: "css"
});
console.log(receiver.type); // "css"
console.log(receiver.name); // "file.js"
ES6 - Objects
function CreatePerson(name, age) {
return { name, age, hello() { return `Hello ${this.name}`;} };
}
let person = new CreatePerson('Ivan', 30);
console.log(person.hello()); // Hello Ivan
// Object.is insead of ===
console.log(Object.is(5, 5)); // true
console.log(Object.is(5, "5")); // false
console.log( Object.is(+0, -0)); // false
console.log( +0 === -0 ); // true
console.log( Object.is(NaN, NaN) ); // true
console.log( NaN === NaN ); // false
// Object.assign
let receiver = {};
Object.assign(receiver, {
type: "js",
name: "file.js"
}, {
type: "css"
});
console.log(receiver.type); // "css"
console.log(receiver.name); // "file.js"
ES6 - Method Objects
let name = "Arni";
let user = {
name,
// вместо "sayHi: function() {" пишем "sayHi() {"
sayHi() {
alert(this.name);
}
};
user.sayHi(); // Arni
ES6 - Objects super
let animal = {
walk() {
alert("I'm walking");
}
};
let rabbit = {
__proto__: animal, // показываем на что ссылается
walk() {
alert(super.walk); // walk() { … }
super.walk(); // I'm walking
}
};
rabbit.walk();
В ES-2015 появилось новое ключевое слово super. Оно предназначено только для использования в методах объекта.
Вызов super.parentProperty позволяет из метода объекта получить свойство его прототипа.
ES6 - Symbols
Новый примитивный тип данных Symbol служит для создания уникальных идентификаторов.
let uid = Symbol.for("uid");
let object = {
[uid]: "12345"
};
console.log(object[uid]); // "12345"
console.log(uid); // "Symbol(uid)"
let uid2 = Symbol.for("uid");
console.log(uid === uid2); // true
console.log(object[uid2]); // "12345"
console.log(uid2); // "Symbol(uid)"
let sym = Symbol();
ES6 - Sets and Maps
Map – коллекция для хранения записей вида ключ:значение.
let map = new Map();
map.set('1', 'str1'); // ключ-строка
map.set(1, 'num1'); // число
map.set(true, 'bool1'); // булевое значение
// в обычном объекте это было бы одно и то же,
// map сохраняет тип ключа
console.log( map.get(1) ); // 'num1'
console.log( map.get('1') ); // 'str1'
console.log( map.size ); // 3
map
.set('1', 'str1')
.set(1, 'num1')
.set(true, 'bool1');
let map = new Map([
['1', 'str1'],
[1, 'num1'],
[true, 'bool1']
]);
ES6 - Sets and Maps
Методы для удаления записей:
- map.delete(key) удаляет запись с ключом key, возвращает true, если такая запись была, иначе false.
- map.clear() – удаляет все записи, очищает map.
Для проверки существования ключа:
- map.has(key) – возвращает true, если ключ есть, иначе false.
ES6 - Sets and Maps
Set – коллекция для хранения множества значений, причём каждое значение может встречаться лишь один раз.
let set = new Set();
let vasya = {name: "Вася"};
let petya = {name: "Петя"};
let dasha = {name: "Даша"};
// посещения, некоторые пользователи заходят много раз
set.add(vasya);
set.add(petya);
set.add(dasha);
set.add(vasya);
set.add(petya);
// set сохраняет только уникальные значения
alert( set.size ); // 3
ES6 - Sets and Maps
// SET
let numbers = [1, 2, 3, 3, 3, 4, 5];
let noDuplicates = [...new Set(numbers)];
console.log(noDuplicates); // [1,2,3,4,5]
let map = new Map([["name", "Ivan"], ["age", 35]]);
// MAP
console.log(map.has("name")); // true
console.log(map.get("name")); // "Nicholas"
console.log(map.has("age")); // true
console.log(map.get("age")); // 35
console.log(map.size); // 2
map.clear();
console.log(map.has("name")); // false
console.log(map.size); // 0
ES6 - Sets and Maps
let arr = [1, 2, 3]; // массив — пример итерируемого объекта
for (let value of arr) {
console.log(value); // 1, затем 2, затем 3
}
Итерируемые или, иными словами, «перебираемые» объекты – это те, содержимое которых можно перебрать в цикле.
Для перебора таких объектов добавлен новый синтаксис цикла: for..of.
for (let char of "Привет") {
console.log(char); // Выведет по одной букве: П, р, и, в, е, т
}
ES6 - Sets and Maps
// default iterator
let values = [1, 2, 3];
let iterator = values[Symbol.iterator]();
console.log(iterator.next()); // "{ value: 1, done: false }"
console.log(iterator.next()); // "{ value: 2, done: false }"
console.log(iterator.next()); // "{ value: 3, done: false }"
console.log(iterator.next()); // "{ value: undefined, done: true }"
ES6 - Sets and Maps
let range = {
from: 1,
to: 5,
[Symbol.iterator]() {
return this;
},
next() {
if (this.current === undefined) {
// инициализация состояния итерации
this.current = this.from;
}
if (this.current <= this.to) {
return {
done: false,
value: this.current++
};
} else {
// очистка текущей итерации
delete this.current;
return {
done: true
};
}
}
};
- Перебираемый объект range сам не реализует методы для своего перебора.
- Для этого создаётся другой объект, который хранит текущее состояние перебора и возвращает значение. Этот объект называется итератором и возвращается при вызове метода range[Symbol.iterator].
-
У итератора должен быть метод next(), который при каждом вызове возвращает объект со свойствами:
- value – очередное значение,
- done – равно false если есть ещё значения, и true – в конце.
ES6 - Generators
function* generateSequence() {
yield 1;
yield 2;
return 3;
}
let generator = generateSequence();
let one = generator.next();
console.log(JSON.stringify(one)); // {value: 1, done: false}
let two = generator.next();
console.log(JSON.stringify(two)); // {value: 2, done: false}
Генераторы – новый вид функций в современном JavaScript. Они отличаются от обычных тем, что могут приостанавливать своё выполнение, возвращать промежуточный результат и далее возобновлять его позже, в произвольный момент времени.
ES6 - Generators and Iterator
function* generateSequence() {
yield 1;
yield 2;
return 3;
}
let generator = generateSequence();
for(let value of generator) {
console.lg(value); // 1, затем 2
}
При запуске примера выше будет выведено значение 1, затем 2. Значение 3 выведено не будет. Это потому что стандартный перебор итератора игнорирует value на последнем значении, при done: true. Так что результат return в цикле for..of не выводится.
ES6 - Generators
function *createIterator() {
yield 1;
return;
yield 2;
}
let iterator = createIterator();
console.log(iterator.next()); // "{ value: 1, done: false }"
console.log(iterator.next()); // "{ value: undefined, done: true }"
ES6 - Classes
class User {
constructor(name) {
this.name = name;
}
sayHi() {
console.log(this.name);
}
}
let user = new User("Arni");
user.sayHi(); // Arni
ES6 - Classes
class PersonClass {
constructor(name) {
this.name = name;
}
sayName() {
console.log(this.name);
}
get name() {
return this.name;
}
set name(value) {
this.namne = value;
}
static create(name) {
return new PersonClass(name);
}
}
ES6 - Classes
class PersonClass {
constructor(name) {
this.name = name;
}
sayName() {
console.log(this.name);
}
get name() {
return this.name;
}
set name(value) {
this.name = value;
}
}
getter and setter
ES6 - Classes
class PersonClass {
constructor(name) {
this.name = name;
}
sayName() {
console.log(this.name);
}
get name() {
return this.name;
}
set name(value) {
this.name = value;
}
static create(name) {
return new PersonClass(name);
}
}
let person = PersonClass.create('Arni');
console.log( person.name ); // Arni
console.log( person.create ); // create ... (function)
static
ES6 - Classes
class PersonClass {
constructor(name) {
this.name = name;
}
sayName() {
console.log(this.name);
}
get name() {
return this.name;
}
set name(value) {
this.name = value;
}
static create(name) {
return new PersonClass(name);
}
}
class SuperPersonClass extends PersonClass {
constructor(name) {
super(`Super ${name}`);
}
}
let superPerson = new SuperPersonClass('Arni');
inheritance
ES6 - Promises
let p1 = new Promise(function(resolve, reject) {
resolve(42);
});
p1.then(function(value) {
console.log(value);
}).then(function() {
console.log("Finished");
}).catch(function(error) {
console.log(error);
});
42
Finished
Async and Await
function logFetch(url) {
return fetch(url)
.then(response => response.text())
.then(text => {
console.log(text);
}).catch(err => {
console.error('fetch failed', err);
});
}
async function logFetch(url) {
try {
const response = await fetch(url);
console.log(await response.text());
} catch (err) {
console.log('fetch failed', err);
}
}
Links
Examples
JS
By Oleg Rovenskyi
JS
JavaScript 2015
- 476