Наследование в JavaScript в через прототипы [дубликат]

208
22 марта 2017, 18:09

На данный вопрос уже ответили:

  • Прототипное наследование 2 ответа

При изучении JavaScript возник вопрос:

Почему при наследовании на основании прототипов нужно делать так:

child.prototype = Object.create(parent.prototype);

а нельзя просто сделать так:

child.prototype = parent

Разве не одно и тоже получаем?

Answer 1

В иерархии прототипного наследования есть 2 типа сущностей - это прототипы(объекты) и конструкторы(функции)

function Parent() {this.name = 'Parent'; this.foo='foo';} 
Parent.prototype.getName = function(){return this.name;}; 
Parent.prototype.getFoo = function(){return this.foo;} 
 
// Заведём функция для теста дочерних "классов" 
function newtest(Ctor) { 
  var test = new Ctor; 
  try{ 
    console.log(test.getName(), test.getFoo(), test instanceof Ctor, test instanceof Parent); 
  } catch(e) {console.error(e.message);} 
  return test; 
} 
 
// Здесь прототипу конструктора присваивается конструктор, функция, 
// у которой нет свойств, которые мы ожидаем увидеть в иерархии 
function Child1() {this.name = 'Child1';} 
Child1.prototype = Parent;   
newtest(Child1); // test.getName is not a function! 
 
// Здесь прототипу присваивается объект, созданный на базе прототипа родителя,  
// у него есть все свойства/методы, которые мы объявили в Parent.prototype 
function Child2() {this.name = 'Child2';} 
Child2.prototype = Object.create(Parent.prototype);   
newtest(Child2); // Child2 undefined 
// конструктор родителя не был выполнен 
 
 
// Непосредственный вызов конструктора, неприменимо, 
// если конструктор родителя имеет параметры  
// либо зависит от внешних факторов/имеет побочные эффекты 
function Child3() {this.name = 'Child3';} 
Child3.prototype = new Parent;   
newtest(Child3); // Child3 foo 
 
// Вызов родительского конструктора из дочернего 
function Child4(){ 
  // this.constructor.call(this); // возможно, потому что св-во constructor у нас сломано - указывает на родительский конструктор 
  Parent.call(this); 
  this.name = 'Child4'; 
} 
Child4.prototype = Object.create(Parent.prototype); 
newtest(Child4); // Child4 foo 
 
// Иногда бывает важно восстановить свойство prototype.constructor в заменённом Child.prototype 
Child4.prototype = Object.create(Parent.prototype, { 
  constructor: {value: Child4, enumerable: false, writable: true, configurable: true} 
}); 
 
 
 
 
// Наиболее распространённая форма наследования до появления Object.create 
// подразумевала создание промежуточного конструктора: 
function extend(P, C) { 
  var F = function (){}; 
  F.prototype = P.prototype; 
  // заменяем прототип вновь созданным объектом с прототипом родителя 
  C.prototype = new F(); 
  // восстанавливаем свой конструктор 
  C.prototype.constructor = C; 
  // ссылка на родительский конструктор, чтобы отвязаться от его имени 
  C.prototype.super = P; 
  // Лучше последние 2 свойства задать через Object.defineProperty, чтобы выставить enumerable: false 
} 
 
function LegacyChild() {this.super(); this.name = 'LegacyChild';} 
extend(Parent, LegacyChild); 
newtest(LegacyChild); // LegacyChild foo

Answer 2

Если по простому и по русски, то делая child.prototype = parent.prototype ты не создаешь новый объек "прототип" ребенка... Не забываем, что в JS обекты передаются по ссылке и в таком случае твой дочерний объект прототипа будет лишь ссылаться на родительский по ссылке. И при добавлении свойств и методов в дочерний (специфические только для него), они так же будут доступны и в родительском.
child.prototype = Object.create(parent.prototype); Делая так, ты создаешь новый обект.

READ ALSO
Как просмотреть значение переменной в cshtml при отладке Visual Studio?

Как просмотреть значение переменной в cshtml при отладке Visual Studio?

При наведении на name не показывает её значение

262
Пустой photos_list при работе с VK API

Пустой photos_list при работе с VK API

Загружаю фотографию к себе в альбом согласно документации:

325
Поле для ввода номера телефона на чистом JS

Поле для ввода номера телефона на чистом JS

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

902
Сравнение двух json-объектов и добавление недостающих элементов

Сравнение двух json-объектов и добавление недостающих элементов

Есть два json-объекта с разным количеством элементовВ первом, допустим, 6 элементов с ключом segment, а во втором - 8

384