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