- PVSM.RU - https://www.pvsm.ru -

Нужны ли в JavaScript классы? часть 2

см. Часть 1 [1]

Производительность: создание классов через __proto__

image
По производительности Object.create к сожалению не дает больших результатов (в особенности со вторым аргументом — дескрипторами). В отличии от использования __proto__ напрямую, который оказался даже быстрее связки функции–конструктора с оператором new — см. jsPerf [2]. Отмечу также, что использование дескрипторов не особо удобно.

CloneJS nano [3]

По вышеизложенным причинам, создадим функцию clone:

function clone(proto, properties){
    properties.__proto__ = proto;
    return properties;
}

Клонирование

В прототип-ориентированных системах предоставляется два метода создания нового объекта: клонирование существующего объекта, либо создание объекта «с нуля». Для создания объекта с нуля программисту предоставляются синтаксические средства добавления свойств и методов в объект. В дальнейшем, с получившегося объекта может быть получена полная копия — клон. В процессе клонирования копия наследует все характеристики своего прототипа, но с этого момента она становится самостоятельной и может быть изменена.

© Wikipedia [4]

Функция clone(), как следует из названия, создает клоны объектов. Клон — это lazy shallow copy, то есть это фактически не копия, а просто ссылка на объект, но, если добавить/заменить какие-либо его свойства, это не отразится на объекте-родителе (прототипе).
Все объекты в JavaScript являются клонами Object.prototype (за исключением его самого и объектов, созданных с помощью Object.create(null)).

/// "Класс"
    var duck$ = {
        name: "Unnamed",
        quack: function(){
            console.log( this.name +" Duck: Quack-quack!");
        }
    };
/// Наследование
    var talkingDuck$ = clone( duck$, {
        quack: function(){
            duck$.quack.call(this);
            console.log("My name is "+ this.name +"!");
        }
    });
/// Инстанцирование
    var donald = clone( talkingDuck$, {name: "Donald"});

Как альтернативу, можно использовать объектно-ориентированный вариант:

/// object$ – прототип всех наших объектов
var object$ = {
    clone: function(properties){
        properties.__proto__ = this;
        return properties;
};

/// "Класс"
    var duck$ = object$.clone({
        name: "Unnamed",
        quack: function(){
            console.log( this.name +" Duck: Quack-quack!");
        }
    };
/// Наследование
    var talkingDuck$ = duck$.clone({
        quack: function(){
            duck$.quack.call(this);
            console.log("My name is "+ this.name +"!");
        }
    });
/// Инстанцирование
    var donald = talkingDuck$.clone({name: "Donald"});

Совместимость

Справедливо заметить, что функция clone на самом деле не создает никаких объектов, а просто изменяет объектy properties его прототип. Это можно легко исправить:

function clone(proto, properties){
    var newObj = {__proto__: proto};
    for(var key in properties) newObj[key] = properties[key];
    return newObj;
}

Но тогда мы потеряем в производительности. Лучше ввести правило:

Использование второго аргумента после клонирования нежелательно, и возможно при использовании исключительно его собственных свойств.

Это правило также позволит обеспечить совместимость с Internet Explorer 6–10 и ECMA Script 3:

    function clone(/** Object */proto, /** ObjLiteral= */ownProperties){
        function Clone(ownProperties){
            for(var key in ownProperties) this[key] = ownProperties[key];
        };
        Clone.prototype = proto;
        
        return new Clone(ownProperties);
    }


Вот примерно так был создан фреймворк clone.js [5].
Нужны ли в JavaScript классы? часть 2

Автор: Quadratoff

Источник [6]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/javascript/42940

Ссылки в тексте:

[1] Часть 1: https://www.pvsm.ru/post/175029/

[2] jsPerf: http://jsperf.com/object-properties-init/4

[3] CloneJS nano: https://github.com/quadroid/clonejs-nano#readme

[4] Wikipedia: http://ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%BE%D1%82%D0%BE%D1%82%D0%B8%D0%BF%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5#.D0.9A.D0.BE.D0.BD.D1.81.D1.82.D1.80.D1.83.D0.B8.D1.80.D0.BE.D0.B2.D0.B0.D0.BD.D0.B8.D0.B5_.D0.BE.D0.B1.D1.8A.D0.B5.D0.BA.D1.82.D0.BE.D0.B2

[5] clone.js: https://github.com/quadroid/clonejs#readme

[6] Источник: http://habrahabr.ru/post/192806/