Наследование JavaScript: Object.create vs new

В JavaScript какая разница между этими двумя примерами:

Необходимое условие:

function SomeBaseClass(){
}

SomeBaseClass.prototype = {
    doThis : function(){
    },

    doThat : function(){
    }
}

Пример наследования A с использованием Object.create:

function MyClass(){
}

MyClass.prototype = Object.create(SomeBaseClass.prototype);

Пример наследования B с использованием нового ключевого слова

function MyClass(){
}

MyClass.prototype = new SomeBaseClass();

Оба примера, похоже, делают то же самое. Когда вы выбрали один за другим?

Дополнительный вопрос: Рассмотрим код в ссылке ниже (строка 15), где ссылка на собственный конструктор функции хранится в прототипе. Почему это полезно?

https://github.com/mrdoob/three.js/blob/master/src/loaders/ImageLoader.js

Выдержка (если вы не хотите открывать ссылку):

THREE.ImageLoader.prototype = {

    constructor: THREE.ImageLoader
}

Ответ 1

В вашем вопросе вы упомянули, что Both examples seem to do the same thing, Это не совсем так, потому что

Ваш первый пример

function SomeBaseClass(){...}
SomeBaseClass.prototype = {
    doThis : function(){...},
    doThat : function(){...}
}
function MyClass(){...}
MyClass.prototype = Object.create(SomeBaseClass.prototype);

В этом примере вы просто наследуете SomeBaseClass' prototype, но что, если у вас есть свойство в SomeBaseClass как

function SomeBaseClass(){ 
    this.publicProperty='SomeValue'; 
}

и если вы используете его как

var obj=new MyClass();
console.log(obj.publicProperty); // undefined
​console.log(obj);​

Объект obj не будет иметь свойство publicProperty, например в этом примере.

Ваш второй пример

MyClass.prototype = new SomeBaseClass();

Выполняет функцию constructor, создавая экземпляр SomeBaseClass и наследуя весь объект SomeBaseClass. Итак, если вы используете

    var obj=new MyClass();
    console.log(obj.publicProperty); // SomeValue
    console.log(obj);​

В этом случае его свойство publicProperty также доступно для объекта obj, такого как в этом примере.

Так как Object.create недоступен в некоторых старых браузерах, в этом случае вы можете использовать

if(!Object.create)
{
    Object.create=function(o){
        function F(){}
        F.prototype=o;
        return new F();
    }
}

Выше кода просто добавляет функцию Object.create, если она недоступна, поэтому вы можете использовать функцию Object.create, и я думаю, что приведенный выше код описывает, что действительно делает Object.create. Надеюсь, это поможет в некотором роде.

Ответ 2

Оба примера, похоже, делают то же самое.

Это верно в вашем случае.

Когда вы выбрали один за другим?

Когда SomeBaseClass имеет тело функции, это будет выполняться с ключевым словом new. Обычно это не предназначено - вы хотите настроить цепочку прототипов. В некоторых случаях это может вызвать серьезные проблемы, поскольку вы фактически создаете экземпляр объекта, чьи переменные с частным окружением разделяются всеми экземплярами MyClass, поскольку они наследуют одни и те же привилегированные методы. Возможны другие побочные эффекты.

Итак, вы обычно предпочитаете Object.create. Тем не менее, он не поддерживается в некоторых устаревших браузерах; что является причиной того, что вы слишком часто наблюдаете new -approach, так как часто не наносит (очевидного) вреда. Также посмотрите этот ответ.

Ответ 3

Разница становится очевидной, если вы используете Object.create() по своему усмотрению. Фактически, он полностью скрывает слово prototype от вашего кода, он выполнит эту работу под капотом. Используя Object.create(), мы можем пойти как

var base =  {
    doThis : function(){
    },

    doThat : function(){
    }
};

И тогда мы можем расширять/наследовать другие объекты из этого

var myObject = Object.create( base );
// myObject will now link to "base" via the prototype chain internally

Итак, это еще одна концепция, более "объектно-ориентированный" способ наследования. Например, нет функции "конструктора", используя Object.create(). Но, конечно же, вы могли бы просто создать и вызвать функцию self defined constructor внутри этих объектов.

Один аргумент для использования Object.create() заключается в том, что было бы более естественно смешивать /* наследовать * от других объектов, чем использовать способ по умолчанию Javascripts.

Ответ 4

Я не эксперт в java script, но вот простой пример, чтобы понять разницу между "Object.create" и "new"..

шаг 1: создать родительскую функцию с некоторыми свойствами и действиями.

function Person() {

this.name = 'venkat';

this.address = 'dallas';

this.mobile='xxxxxxxxxx'

}

Person.prototype.func1 = function () {

    return this.name + this.address;
}

Шаг 2: создайте дочернюю функцию (PersonSalary), которая распространяется выше функции Person, используя ключевое слово Новое.

function PersonSalary() {
    Person.call(this);
}
PersonSalary.prototype = new Person();

PersonSalary();

Шаг 3: создайте вторую дочернюю функцию (PersonLeaves), которая распространяется выше функции Person, используя ключевое слово Object.create.

function PersonLeaves() {
 Person.call(this);
}
PersonLeaves.prototype = Object.create(Person.prototype);


PersonLeaves();

//Теперь проверьте прототипы обоих дочерних функций.

PersonSalary.prototype
PersonLeaves.prototype

обе эти дочерние функции свяжутся с прототипом Person (родительской функции) и могут получить доступ к ним, но если вы создадите дочернюю функцию с помощью new, она вернет совершенно новый объект со всеми родительскими свойствами, которые нам не нужны, а также когда вы создаете любой объект или функцию, используя "New", чтобы выполнялась эта родительская функция, которой мы не хотим быть.

Вот выдержки

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