2013-04-18 5 views
3

У меня есть вопрос для васНужно ли нам переходить на Object.create?

Как я знаю, new оператор работает таким образом

function fakeNew(Ctor) { 
    var instance = Object.create(Ctor.prototype); 
    instance.constructor(); 
    // I skip the conditional for simplicity 
    return instance; 
} 

все это началось, когда я сделал Object.create Polifill, чтобы я мог создавать объекты без использования new.

Object.create = function(proto) { 
    function F() { } 
    F.prototype = proto; 
    return new F(); 
} 

Я начал создавать много objcts и prototiping их, но, как много раз, то нужно initializa своих свойств я сделал метод .init() им

var base = { 
    init: function() { 
    EmitterMixin.call(this); 
    return this; 
    } 
}; 

var obj = Object.create(base).init(); 

Но, конечно, я должен был rembember возвращать this всегда от .init() и много раз я забыл об этом или худшем, я забыл позвонить .init(). Поэтому, пытаясь упростить инициализацию объектов, я хотел создать глобальный помощник, чтобы сделать это: invoke Object.create, вызвать функцию инициализатора и вернуть это.

function create(proto) { 
    var child = Object.create(proto); 
    child.init(); 
    return child; 
} 

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

Так что я спрашиваю себя, какие выгоды выбрасывает new? Это notably quicker в главных браузерах, и из-за характера javascript обычно нужно вызвать функцию initualizer, что-то, чем new делает с самого начала.

И хуже всего, я заметил, чем я использовал два различных типа объектов, «абстрактный» и «случаи», тем больше разница в том, чем для случаев, я должен был вызвать .init() в то время как с аннотациями не было necesasary, потому что они будут использоваться только для прототипов других объектов. И я уже видел эту картину во время использования new:

function Foo() { } 
Foo.prototype.method = function() { ... }; 

function Bar() { } 
// "abstract" doesnt invoke initializer 
Bar.prototype = Object.create(Foo.prototype); 
Bar.prototype.other = function() { ... }; 

// "instance", the constructor is called as initializer 
var obj = new Bar(); 

Есть ли действительно пользу, если мы перестанем видеть new? мы уверены, что это не инструмент более высокого уровня, чем упрощает что-то, что нам придется делать в любом случае? Какие плюсы/минусы вы видите о new и Object.create?

+0

Основные [аргументы против 'нового'] (http: // stackoverflow.com/questions/383402/is-javascript-s-new-keyword-considered-harmful) - «наносит много вреда, когда забывается» и «напоминает слишком много классового наследования» – Bergi

ответ

1

Я пробовал оба подхода, и я лично не вижу никаких проблем с традиционным подходом, используя new. Основным аргументом для Object.create является то, что он делает простейшее наследование более понятным - вам не нужно понимать сложность свойства prototype на конструкторах функций и то, как это относится к фактическому прототипу объекта. Но для этого требуется, чтобы инициализация была отдельным шагом.

Мой предпочтительный подход заключается в объединении двух подходов, например.:

function Animal(name) { 
    this.name = name || null; 
} 
Animal.prototype.eat = function() { 
    console.log('yum'); 
} 

function Cat(name) { 
    Animal.call(this, name); 
} 
Cat.prototype = Object.create(Animal.prototype); 
Cat.prototype.constructor = Cat; 

Cat.prototype.meow = function() { 
    console.log('meow'); 
} 

var garfield = new Cat('garfield'); 
garfield.eat(); 
garfield.meow(); 

Object.create лучше для наследования здесь, чем Cat.prototype = new Animal() по двум причинам:

  1. Если вы хотите, чтобы потребовать от параметра name (метание исключение, если он не был принят), вы могли бы сделать так, и наследование (Cat.prototype = Object.create(Animal.prototype)) все равно будет работать.
  2. Если вы забыли вызвать конструктор Cat из конструктора Animal, все свойства, которые были бы созданы конструктором Animal, будут не определены, что позволит вам быстро реализовать эту ошибку.

Хотя этот подход (с помощью функции конструкторы и new) меньше «чисто» прототипичного, это еще прототипичное наследство и до тех пор, как вы понимаете, как использовать его правильно, это работает очень хорошо, и требует немного меньше типизации, чем подход Object.create.

Я написал несколько других заметок об этом в документации для моей библиотеки OO Javascript, simpleoo. (Примечание: я могу изменить API в ближайшее время для этой библиотеки, я связываюсь с ним главным образом потому, что документация более подробно обсуждает некоторые из этих понятий.)

Смежные вопросы