напрямую назначать .prototype для наследования классов - PullRequest
0 голосов
/ 08 ноября 2019

Мы знаем, что классический способ выполнения наследования - Teacher.prototype = Object.create(Person.prototype);, где Teacher расширяется Person. Однако, если я делаю прямое назначение, это, кажется, тоже работает.

Teacher.prototype = Person.prototype;

Могу я просто сделать это? Теперь Teacher также имеет доступ ко всем методам-прототипам Person.

Ответы [ 2 ]

2 голосов
/ 08 ноября 2019

Вы можете , но это будет означать, что когда вы присваиваете свойство Teacher.prototype, вы будете мутировать Person.prototype, что, вероятно, нежелательно.

// Works:
function Person(name) {
  this.name = name;
}
Person.prototype.getName = function() {
  return this.name;
}
function Teacher(name) {
  Person.call(this, name);
}
Teacher.prototype = Object.create(Person.prototype);
Teacher.prototype.teaches = function() {
  return true;
}

const p = new Person('bob');
console.log(p.teaches()); // p.teaches is not a function, as expected and desired

Сравнить с

// Bad:
function Person(name) {
  this.name = name;
}
Person.prototype.getName = function() {
  return this.name;
}
function Teacher(name) {
  Person.call(this, name);
}
Teacher.prototype = Person.prototype;
Teacher.prototype.teaches = function() {
  return true;
}

const p = new Person('bob');
console.log(p.teaches()); // `true`... oops, but bob is not a Teacher, bob is just a Person

Лучше использовать метод Object.create, чтобы Teacher.prototype (изначально, по крайней мере) был пустым объектом , свободным для мутации, который имеет внутренний прототип , указывающий на Person.prototype.

Имейте в виду, что для реального кода (а не кода, используемого для мысленного эксперимента радипонимания языковой механики), вы можете избежать многих неприятностей и синтаксических помех, используя class и ключевое слово extends:

class Person {
  constructor(name) {
    this.name = name;
  }
  getName() {
    return this.name;
  }
}
class Teacher extends Person {
  teaches() {
    return true;
  }
}
const p = new Person('bob');
console.log(p.teaches()); // p.teaches is not a function, as expected and desired
1 голос
/ 08 ноября 2019

Иногда это прямое назначение прототипов имеет смысл, а именно, когда вы хотите, чтобы один и тот же объект создавался различными способами - аналогично перегруженным конструкторам в Java. Например:

function Rectangle(w, h) {
    this.w = w;
    this.h = h;
}

Rectangle.prototype.area = function() {
    return this.w * this.h;
}

function RectangleFromCoords(x1, y1, x2, y2) {
    this.w = x2 - x1;
    this.h = y2 - y1;
}

RectangleFromCoords.prototype = Rectangle.prototype;

let a = new Rectangle(20, 10);
console.log(a instanceof Rectangle, a.area())

let b = new RectangleFromCoords(20, 25, 10, 15);
console.log(b instanceof Rectangle, b.area())

Но в вашем примере, поскольку "Персона" и "Учитель", очевидно, разные объекты, Teacher.prototype = Person.prototype неверен, потому что в основном говорит "каждый учитель - это человек »(что хорошо) И« каждый человек является учителем »(не все в порядке).

...