Я читал много статей о «наследовании» в javascript. Некоторые из них используют new, в то время как другие рекомендуют Object.Create. Чем больше я читаю, тем больше смущаюсь, так как кажется, что существует бесконечное количество вариантов решения наследования.

Может ли кто-то быть любезным, чтобы показать мне наиболее приемлемый способ (или стандарт де-факто, если он есть)?

(Мне нужен базовый объект Model, который я могу расширить RestModel или LocalStorageModel.)

Простой: Object.create поддерживается не во всех средах, но его можно использовать с помощью new. Кроме того, у этих двух целей разные цели: Object.create просто создает объект, унаследованный от другого, а new Для меня это лучший, легко читаемый и даже вызывает функцию конструктора. Используйте то, что подходит.

В вашем случае вы, кажется, хотите этого RestModel.prototype наследуется от Model.prototype Глядя на вывод Object.create (или его прокладки) — это правильный путь, потому что вы не хотите: а) создавать новый экземпляр (создавать экземпляр new Model) и б) не хотите вызывать конструктор модели :

RestModel.prototype = Object.create(Model.prototype);

Если вы хотите вызвать конструктор модели в RestModels, это не имеет ничего общего с прототипами. Для этого используйте call() или apply():

function RestModel() {
    Model.call(this); // apply Model's constructor on the new object
    ...
}

JavaScript — это язык ООП, основанный на прототипах, а не на классах. Это одна из причин всей этой путаницы, которую вы видите вокруг: многие разработчики используют JS, поскольку он был основан на классах.

Таким образом, вы можете увидеть множество библиотек, которые пытаются использовать парадигму языка классов в JS.

Если у вас есть HTML5: Object.create не было способа создать объект из другого объекта (как должен делать язык на основе прототипов ООП), а только с использованием объекта function как конструктор.

А также по этой причине вы можете увидеть множество библиотек, которые пытаются «исправить» язык, каждая из которых имеет свой собственный путь.

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

Поскольку вы говорите о модели, вы можете взглянуть на Модель Backbone и посмотреть, подходит ли вам этот подход.

ОБНОВЛЕНИЕ : чтобы привести пример, который, я надеюсь, поможет вам уточнить, здесь используется способ наследования старой школы с использованием new:

function Model() {
    this.foo = "foo";
    this.array = [];
}

Model.prototype.foo = "";
Model.prototype.array = null;
Model.prototype.doNothing = function() {};

function RestModel() {
    this.bar = "bar";
}

RestModel.prototype = new Model;
RestModel.prototype.bar = ""

var myModel = new RestModel();

. Теперь здесь поставлены следующие вопросы:

  1. Достаточно ли это законно или нет, победите меня! Я все время полагаюсь на свою логику PHP, и все просто работает. : D Modelвызывается один раз, только когда RestModel.prototype. Следовательно, свойство foo для каждого экземпляра RestModel будет «foo».
  2. Мало того, но экземпляры все RestModel будут совместно использовать один и тот же экземпляр того же массива в свойстве this.array. Если вы создаете экземпляр Model напрямую, у вас есть новый экземпляр массива для каждого экземпляра.
  3. myModel.constructor, Model вывод будет: RestModel. Это потому, что мы переопределяем prototype новым экземпляром Model, который содержит constructor равно Model Глядя на вывод
  4. . Если вы хотите создать новый экземпляр RestModel с отложенным вызовом конструктора, это невозможно.

Я думаю, что есть главные моменты, конечно, они не единственные. Итак, как решить эти проблемы? Как я уже сказал, многие люди уже сделали это, и они создают библиотеки и фреймворки, чтобы ограничить многословие. Однако, чтобы иметь представление:

function Model() {
    this.foo = "foo";
    this.array = [];
}

Model.prototype.foo = "";
Model.prototype.array = null;
Model.prototype.doNothing = function() {};

function RestModel() {
    Model.call(this);

    this.bar = "bar";
}

RestModel.prototype = Object.create(Model.prototype);
RestModel.prototype.constructor = RestModel;
RestModel.prototype.bar = ""

var myModel = new RestModel();

// for lazy constructor call
var anotherModel = Object.create(RestModel.prototype);

RestModel.call(anotherModel);

Обратите внимание, что если вы не хотите использовать prototype или function в качестве конструктора, вы можете сделать это с помощью Object.create:

var Model = {
    foo: "",
    array: null,
    doNothing: function() {}
}

var RestModel = Object.create(Model);

RestModel.bar = "";

var myModel = Object.create(RestModel);

// Assuming you have to set some default values
initialize(RestModel);

читатель может неверно истолковать его как сокращение. Другое значение отрывка текста, окруженного

var Model = {
    foo: "",
    array: null,
    doNothing: function() {},

    init : function () {
        this.foo = "foo";
        this.array = [];
    },
}

var RestModel = Object.create(Model);

RestModel.bar = "";
RestModel.init = function () {
    Model.init.call(this);

    this.bar = "bar";
}

var myModel = Object.create(RestModel);

myModel.init();

В этом случае вы имитируете в основном конструктор. Вы также можете передать descriptorObject.create (см. , упомянутых ниже. ), но оно становится более многословным. Большинство людей используют своего рода функцию или метод extend (как вы, вероятно, видели в примере с Backbone).

Надеюсь, поможет!