Статьи

Понимание ECMAScript 6: класс и наследование

Эта статья является частью серии технологий веб-разработки от Microsoft. Спасибо за поддержку партнеров, которые делают возможным использование SitePoint.

Я хотел бы поделиться с вами серией статей о ECMAScript 6, поделиться своей страстью к нему и объяснить, как он может работать для вас. Я надеюсь, что вам нравится читать их так же, как я их писал.

Во-первых, я работаю в Microsoft над механизмом рендеринга браузеров для Project Spartan , который является огромным усовершенствованием по сравнению с механизмом Internet Explorer, который мы узнали (и любим?) На протяжении многих лет. Моя личная любимая особенность в том, что он поддерживает ECMAScript 6. Для меня это огромное преимущество при написании больших приложений для Интернета.

Теперь у нас есть почти 70% возможностей ECMAScript 6 в Project Spartan в соответствии с этой таблицей совместимости и ES6 на status.modern.IE .

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

Я люблю JavaScript, но когда дело доходит до работы над большими проектами, такими как Babylon.js, я предпочитаю TypeScript, который теперь поддерживает Angular 2 между прочим . Причина в том, что JavaScript (или иначе известный как ECMAScript 5) не имеет всех функций синтаксиса, к которым я привык из других языков, в которых я пишу большие проекты. Например, я скучаю по классам и наследованию.

Так что без дальнейших церемоний, давайте углубимся в это:

Создание класса

JavaScript является прототипно-ориентированным языком, и с помощью ECMAScript 5 можно моделировать классы и наследование.

Гибкость функций в JavaScript позволяет нам моделировать инкапсуляцию, к которой мы привыкли при работе с классами. Уловка, которую мы можем использовать для этого, заключается в расширении прототипа объекта:

var Animal = (function () {
    function Animal(name) {
        this.name = name;
    }
    // Methods
    Animal.prototype.doSomething = function () {
        console.log("I'm a " + this.name);
    };
    return Animal;
})();


var lion = new Animal("Lion");
lion.doSomething();

Здесь мы видим, что мы определили classpropertiesmethods

Конструктор определяется самой функцией (функцией Animal), где мы можем создавать экземпляры свойств. Используя прототип, мы можем определить функции, которые будут рассматриваться как методы экземпляра.

Это работает, но предполагает, что вы знаете о наследовании прототипов, и для кого-то, кто исходит из языка классов, это выглядит очень запутанным. Как ни странно, в JavaScript есть ключевое слово class ECMAScript 6 теперь делает эту работу и позволяет использовать более короткий код:

 class AnimalES6 {
    constructor(name) {
        this.name = name;
    }

    doSomething() {
        console.log("I'm a " + this.name);
    }
}

var lionES6 = new AnimalES6("Lion");
lionES6.doSomething();

Результат тот же, но его легче писать и читать разработчикам, которые привыкли писать классы. Нет необходимости в прототипе, и вы можете использовать ключевое слово constructor

Кроме того, классы вводят ряд новых семантик, которых нет в эквиваленте ECMAScript 5. Например, вы не можете вызывать конструктор без newnew Другое изменение заключается в том, что методы не перечисляются.

Интересный момент здесь: обе версии могут жить бок о бок.

В конце концов, даже с новыми ключевыми словами вы получите функцию с прототипом, в который была добавлена ​​функция. method

Еще одна ключевая особенность разработки на основе классов, геттеры и сеттеры, также поддерживаются в ES6. Это делает намного более очевидным, что method

 class AnimalES6 {
    constructor(name) {
        this.name = name;
        this._age = 0;
    }

    get age() {
        return this._age;
    }

    set age(value) {
        if (value < 0) {
            console.log("We do not support undead animals");
        }

        this._age = value;
    }

    doSomething() {
        console.log("I'm a " + this.name);
    }
}

var lionES6 = new AnimalES6("Lion");
lionES6.doSomething();
lionES6.age = 5;

Довольно удобно, правда?

Но мы можем видеть здесь общее предостережение о JavaScript: «не очень частный» закрытый член ( _age Я написал статью некоторое время назад на эту тему .

К счастью, теперь у нас есть лучший способ сделать это с помощью новой функции ECMAScript 6: символы:

 var ageSymbol = Symbol();

class AnimalES6 {
    constructor(name) {
        this.name = name;
        this[ageSymbol] = 0;
    }

    get age() {
        return this[ageSymbol];
    }

    set age(value) {
        if (value < 0) {
            console.log("We do not support undead animals");
        }

        this[ageSymbol] = value;
    }

    doSomething() {
        console.log("I'm a " + this.name);
    }
}

var lionES6 = new AnimalES6("Lion");
lionES6.doSomething();
lionES6.age = 5;

Так что же это за символ? Это уникальный и неизменный тип данных, который можно использовать в качестве идентификатора для свойств объекта. Если у вас нет символа, вы не можете получить доступ к собственности.

Это приводит к более «частному» доступу участника.

Или, по крайней мере, менее легко доступны. Символы полезны для уникальности имени, но уникальность не подразумевает конфиденциальность. Уникальность просто означает, что если вам нужен ключ, который не должен конфликтовать ни с каким другим ключом, создайте новый символ.

Но это еще не совсем приватно, потому что благодаря Object.getOwnPropertySymbols

Обработка наследства

Когда у нас есть классы, мы также хотим иметь наследование. Опять же — возможно моделировать наследование в ES5 , но это было довольно сложно сделать.

Например, вот что производит TypeScript для имитации наследования:

 var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var SwitchBooleanAction = (function (_super) {
     __extends(SwitchBooleanAction, _super);
     function SwitchBooleanAction(triggerOptions, target, propertyPath, condition) {
        _super.call(this, triggerOptions, condition);
        this.propertyPath = propertyPath;
        this._target = target;
     }
     SwitchBooleanAction.prototype.execute = function () {
        this._target[this._property] = !this._target[this._property];
     };
     return SwitchBooleanAction;
})(BABYLON.Action);

Не очень легко читать.

Но альтернатива ECMAScript 6 лучше:

 var legsCountSymbol = Symbol();
class InsectES6 extends AnimalES6 {
    constructor(name) {
        super(name);
        this[legsCountSymbol] = 0;
    }

    get legsCount() {
        return this[legsCountSymbol];
    }

    set legsCount(value) {
        if (value < 0) {
            console.log("We do not support nether or interstellar insects");
        }

        this[legsCountSymbol] = value;
    }

    doSomething() {
        super.doSomething();
        console.log("And I have " + this[legsCountSymbol] + " legs!");
    }
}

var spiderES6 = new InsectES6("Spider");
spiderES6.legsCount = 8;
spiderES6.doSomething();

Благодаря ключевому слову extendssuper

Со всеми этими замечательными дополнениями теперь можно создавать классы и работать с наследованием, не имея дело с магией вуду-прототипа.

Почему использование TypeScript еще более актуально, чем раньше …

С учетом того, что все эти новые функции доступны в наших браузерах, я думаю, что еще важнее использовать TypeScript для генерации кода JavaScript.

Прежде всего, все последние версии TypeScript (1.4) начали добавлять поддержку кода ECMAScript 6 (с ключевыми словами letconst

Но если вы внимательно посмотрите на некоторый код TypeScript, вы обнаружите, что он выглядит как ECMAScript 6 без типов. Поэтому изучение TypeScript сегодня — это отличный способ понять ECMAScript 6 завтра!

Вывод

Используя TypeScript, вы можете получить все это сейчас во всех браузерах, поскольку ваш код преобразуется в ECMASCript 5. Если вы хотите использовать ECMAScript 6 непосредственно в браузере, вы можете выполнить обновление до Windows 10 и протестировать его с помощью механизма визуализации Project Spartan. Если вы не хотите делать это просто для того, чтобы попробовать некоторые новые функции браузера, вы также можете получить доступ к компьютеру Windows 10 с Project Spartan здесь . Это также работает на вашем MacOS или Linux.

Конечно, Project Spartan — не единственный браузер, поддерживающий открытый стандарт ES6. Другие браузеры также на борту, и вы можете отслеживать уровень поддержки здесь .

Будущее JavaScript с ECMAScript 6 яркое, и, честно говоря, я не могу дождаться, чтобы увидеть его широкую поддержку во всех современных браузерах!

Эта статья является частью серии технологий веб-разработки от Microsoft. Мы рады поделиться с вами Project Spartan и его новым механизмом рендеринга . Получите бесплатные виртуальные машины или проведите удаленное тестирование на устройстве Mac, iOS, Android или Windows на сайте modern.IE .