Объявления

  • В четверг последняя лекция по вёрстке
  • В следующий вторник последняя лекция по JS
  • Домашняя работа по JS будет в пятницу
projector test

lecture.theme is undefined

 

 

Марков Евгений

Mocha/LiveScript/JavaScript

ECMAScript

Эволюция ECMAScript

  • ES1, ES2 — первая редакция
  • ES3 (1999) — RegExp, try/catch
  • ES4 — ...
  • ES5 (2009) — строгий режим, геттеры и сеттеры, нативная поддержка JSON, новые методы Array и Object

Пример кода на ES5


              function Student(firstName, lastName) {
                this.firstName = firstName;
                this.lastName = lastName;
              };
            

              Object.defineProperty(Student.prototype, "name", {
                get: function() {
                  return this.firstName + " " + this.lastName;
                }
              });
            

              Student.prototype.setSkills = function(skills) {
                this.skills = skills || [];
              };
            

ES2015 (ES6) — глобальное обновление языка

Классы


                class Student {
                  constructor(firstName, lastName) {
                    this.firstName = firstName;
                    this.lastName = lastName;
                  }

                  get name() {
                    return `${this.firstName} ${this.lastName}`;
                  }

                  setSkills(skills = []) {
                    this.skills = skills;
                  }
                }
              

let и const


                function foo() {
                  var apples = 5;
                }
              

                {
                  let apples = 10;
                }
              

                {
                  const apples = 15;
                }
              

Стрелочные функции


                // краткий синтаксис
                const func = x => x * x;

                // блочный синтаксис
                const func = (x, y) => { return x + y; };
              

Шаблонные строки


                `строка текста`

                `строка текста 1
                  строка текста 2`

                `строка текста ${выражение} строка текста`
              

Деструктуризация массивов


                var zero, one, two;
                var numbers = ['zero', 'one', 'two'];

                zero = numbers[0];
                one = numbers[1];
                two = numbers[2];
              

                const numbers = ['zero', 'one', 'two'];
                const [zero, one, two] = numbers;
              

Деструктуризация объектов


                var p, q;
                var obj = { p: 42, q: true };

                p = obj.p;
                q = obj.q;
              

                const obj = { p: 42, q: true };
                const { p, q } = obj;
              

Промисы


                const promise = new Promise((resolve, reject) => {
                  setTimeout(() => resolve("result"), 1000);
                  setTimeout(() => reject(new Error("ignored")), 2000);
                });

                promise.then(
                  result => alert("Fulfilled: " + result),
                  error => alert("Rejected: " + error)
                );
              

ECMAScript 2016

Оператор возведения в степень


                2 ** 3 // 8
                3 ** 2 // 9
                3 ** 2.5 // 15.588457268119896
                10 ** -1 // 0.1
              

Метод includes у Array и String


                const str = "Быть или не быть вот в чём вопрос.";

                str.includes("Быть"); // true
                str.includes("вопрос"); // true
                str.includes("несуществующий"); // false
              

ECMAScript 2017

async/await


                async function getAuthorAvatar(article) {
                  const userResponse = await fetch(`/articles/${article}`);
                  const { author } = await userResponse.json();

                  const avatarResponse = await fetch(`/avatars/${author.id}`);
                  const avatar = await avatarResponse.json();

                  return avatar.url;
                }
              

ECMAScript 2018

Операторы Rest и Spread для массивов


                const numbers = [1, 2, 3, 4, 5];
                const [first, second, ...others] = numbers;
                console.log(others); // [3, 4, 5]
              


                const others = [3, 4, 5];
                const numbers = [1, 2, ...others];
              

Операторы Rest и Spread для объектов


              const numbers = {
                zero: 1,
                one: 2,
                three: 3,
                four: 4
              };
              const { zero, one, ...others } = numbers;
              console.log(others); // { three: 3, four: 4 }
            


              const others = { three: 3, four: 4 };
              const numbers = { zero: 1, one: 2, ...others };
            

Снова промисы


                fetch('file.json')
                  .then(data => data.json())
                  .catch(error => console.error(error))
                  .finally(() => console.log('finished'));
              

Дальнейшее развитие ECMAScript

GitHub logo

tc39/ecma262

Зачем всё это знать?

Статистика использования браузеров

Браузеры в России по данным Яндекс.Метрики Данные из отчёта «Яндекс.Радара» на 18 ноября 2018

Таблица совместимости

https://kangax.github.io/compat-table

Разный уровень поддержки языка

Venn Diagram
Как решать проблему?

Транспиляция — это процесс перевода исходного кода одного языка в другой

Transpilation

Babel Playground

How Babel works

Код на ES2015


            class Student {
              constructor(firstName, lastName) {
                this.firstName = firstName;
                this.lastName = lastName;
              }

              setSkills(skills = []) {
                this.skills = skills;
              }
            }
          

Код после транспиляции


            var Student = function () {
              function Student(firstName, lastName) {
                _classCallCheck(this, Student);

                this.firstName = firstName;
                this.lastName = lastName;
              }

              _createClass(Student, [{
                key: "setSkills",
                value: function setSkills() {
                  var skills =
                    arguments.length > 0 &&
                    arguments[0] !== undefined ? arguments[0] : [];

                  this.skills = skills;
                }
              }]);

              return Student;
            }();
          

Система плагинов

Plugins

  • arrow-functions
  • classes
  • destructuring
  • duplicate-keys
  • for-of
  • ...

Эксперименты


              const nestedNumbers = {
                one: {
                  two: {
                    three: 42
                  }
                }
              };

              const answer = nestedNumbers?.one?.two?.three; // 42

              const safe = nestedNumbers?.four?.five?.baz; // undefined
            
Pause

Что не так?


            function addNumbers(a, b) {
              return a + b;
            }
          

            addNumbers(2, 2); // 4
          

              addNumbers(2, '2');
            

              // '22'
            

              addNumbers([], []);
            

              // ''
            

              addNumbers([], {});
            

              // [object Object]
            

              addNumbers({}, []);
            

              // 0
            

Как исправить?


              function addNumbers(a, b) {
                if (typeof a !== 'number' || typeof b !== 'number') {
                  throw new Error();
                }

                return a + b;
              }
            

Что в IDE?

no IDE completion

Слабая динамическая типизация

  • Неявные преобразования
  • Типы становятся известны на этапе выполнения

TypeScript Playground

TypeScript venn diagram

Автор языка

Anders Hejlsberg
Андерс Хейлсберг
Известен также по Turbo Pascal, Delphi, C#

Возможности

  • ES2015-ESNext
  • Транспиляция в ES3, ES5, ES2015, ...
  • Аннотации типов и проверка
  • Вывод типов
  • Интерфейсы
  • Обобщённые типы
  • Кортежи

Примитивные типы данных

Boolean


                let isDone: boolean = false;
              

Number


                const decimal: number = 6;
                const hex: number = 0xf00d;
                const binary: number = 0b1010;
                const octal: number = 0o744;
              

String


                const color1: string = "blue";
                const color2: string = 'red';

                const fullName: string = `Arkady`;
                const sentence: string = `Hello, my name is ${fullName}.`;
              

null, undefined


                const u: undefined = undefined;
                const n: null = null;
              

Array


                const list1: number[] = [1, 2, 3];
                const list2: Array<number> = [1, 2, 3];
              

Tuple


                // Объявление кортежа
                let point: [number, number];

                // Некорректная инициализация
                point = [10, 'hello']; // Error

                // Инициализация
                point = [20, 10]; // OK

                // Обращение
                point[1]; // 10

                // Деструктуризация
                const [first, second] = point;
              

Enum


              enum Color {
                Red,
                Green,
                Blue
              }

              const c: Color = Color.Green;
            

              enum Color {
                Red = 5,
                Green = 7,
                Blue = 9
              }

              enum Color {
                Red = '#F00',
                Green = '#0F0',
                Blue = '#00F'
              }
            

Object


                  const colors: object = {
                    red: '#F00',
                    green: '#0F0',
                    blue: '#00F'
                  }
                

                  const settings: {
                    color: string;
                    delay: number;
                    retry: boolean;
                  } = {
                    color: '#F00',
                    delay: 2000,
                    retry: false
                  };
                

Any


              let notSure: any = 4;
              notSure = "maybe a string instead";
              notSure = false;

              let notSure: any = 4;
              notSure.ifItExists(); // Ошибка в рантайме
              notSure.toFixed(); // Всё ок, toFixed есть в рантайме

              let prettySure: object = 4;
              prettySure.toFixed(); // toFixed нет у object
            

Void и Never


              function warnUser(): void {
                console.log("This is my warning message");
              }

              function error(message: string): never {
                  throw new Error(message);
              }

              function infiniteLoop(): never {
                  while (true) {}
              }
            

Приведение типов


              const someValue: any = 'this is a string';

              const strLength1: number = (<string>someValue).length;
              const strLength2: number = (someValue as string).length;
            

Функции


              function add(x: number, y: number): number {
                return x + y;
              }
            

              const add = (x: number, y: number): number => x + y;
            

Интерфейсы


                function printLogin(user: { login: string }) {
                  console.log(user.login);
                }

                const user = {
                  login: 'savichev'
                };

                printLogin(user);
              

Интерфейсы


                interface IUser {
                  login: string;
                }

                function printLogin(user: IUser) {
                  console.log(user.login);
                }

                const user = {
                  username: 'savichev'
                };

                printLogin(user);
              

Опциональные свойства


              interface ISquareConfig {
                color?: string;
              }

              function createSquare(config: SquareConfig) {
                const newSquare = { color: "white", area: 100 };

                if (config.color) {
                    newSquare.color = config.color;
                }

                return newSquare;
              }

              let mySquare = createSquare({ color: "black" });
            

Классы


                interface IMakesSound {
                  makeSound(): void;
                }
              


                class Python implements IMakesSound {
                  private readonly _length: number;

                  public get length() {
                    return this._length / 100;
                  }

                  constructor(length: number) {
                    this._length = length;
                  }

                  protected makeSound() {
                    console.log('Ssssss!');
                  }
                }
              

                abstract class Snake {
                  private readonly _length: number;

                  public get length() {
                    return this._length / 100;
                  }

                  constructor(length: number) {
                    this._length = length;
                  }

                  protected abstract makeSound(): void;
                }
              

                class Python extends Snake {
                  private static population = 10000;

                  public static incrementPopulation() {
                    Python.population++;
                  }

                  constructor(length: number) {
                    super(length);
                    Python.incrementPopulation();
                  }

                  protected makeSound() {
                    console.log('Ssssss!');
                  }
                }
              

              var Snake = (function() {
                function Snake(length) {
                  this._length = length;
                }

                Object.defineProperty(
                  Snake.prototype,
                  "length",
                  {
                    get: function() {
                      return this._length / 100;
                    },
                    enumerable: true,
                    configurable: true
                  }
                );

                return Snake;
              })();
            

              var Python = (function(_super) {
                __extends(Python, _super);

                function Python(length) {
                  var _this = _super.call(this, length) || this;
                  Python.incrementPopulation();
                  return _this;
                }

                Python.incrementPopulation = function() {
                  Python.population++;
                };

                Python.prototype.makeSound = function() {
                  console.log("Ssssss!");
                };

                Python.population = 10000;

                return Python;
              })(Snake);
            

Плагины для IDE

Visual Studio Code

WebStorm

  • Всё есть "из коробки"

Почитать

Посмотреть

Спасибо!

Вопросы?