2016-09-14 2 views
0

Возможно, я читал 15 разных книг, статей или вопросов, связанных с прототипом JavaScript, и каждый из них имел несколько разные способы делать вещи, поэтому я хотел разобраться в этом раз и навсегда:Настройка наследования прототипа

Пример

function Rectangle(h, w){ 
    this.height = h; 
    this.width = w; 
    console.log("Rectangle ctor: "+ this.height + "x" + this.width); 
} 

Rectangle.prototype.getArea = function(){ 
    return this.height * this.width; 
} 

var a = new Rectangle(3, 4); 

console.log(a.getArea()); 

function Square(l){ 
    this.height = l; 
    this.width = l; 
    console.log("Square ctor"); 
} 

Square.prototype = new Rectangle(); 
Square.prototype.constructor = Square; 

var b = new Square(5); 

console.log(b.getArea()); 

Этот пример работает, как ожидалось. Объект Square наследуется от Rectangle, поэтому он имеет возможность использовать метод getArea(). Тем не менее, есть одна вещь, которую я всегда вижу, что делаю по-другому в зависимости от того, где я смотрю.

Вместо того, чтобы делать Square.prototype = new Rectangle(), я видел, как люди используют Square.prototype = Object.create(Rectangle.prototype). Когда я проверить это, как по всей видимости, функционируют таким же образом, единственное различие я замечаю, когда я делаю это:

console.log(new Rectangle()); 
console.log(Object.create(Rectangle.prototype)); 

Это регистрирует new Rectangle() который включает в height и width свойства, затем регистрирует Object.create(Rectangle.prototype), который регистрирует то же самое, за исключением height и width.

Так что мой вопрос: почему некоторые люди делают это с одним, а не с другим? Это более выгодно, чем другое? Как я понимаю, тот, который использует new Rectangle(), получит свойства высоты и ширины на своем прототипе, что может привести к проблемам, правильно?

Может кто-то пролить свет на это? Благодаря!

EDIT

Я также понял, что при использовании new Rectangle() в качестве прототипа площади, он на самом деле вызывает конструктор (который может сделать что-то полезное в некоторых случаях), в то время как метод Object.create() не делает. Является ли обоснование двух разных способов использования, связанных с вариантом использования, в том, следует ли вызывать конструктор для создания некоторого состояния объекта, которое может понадобиться в подтипе?

+0

Раз и навсегда? Используйте синтаксис ES6 'class'. – Bergi

+0

Да, но не все браузеры могут использовать ES6 еще, и я не использую Babel в данный момент. Плюс его больше о понимании, что происходит под капотом, который меня интересует. –

ответ

1

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

Также в ECMAScript 6 вы можете использовать class syntax, что упрощает многие вещи, такие как наследование.

+0

Хорошо спасибо, я думаю, я больше пытаюсь определить, является ли одна версия технически «устаревшей» или если они оба полностью действительны в зависимости от вашего варианта использования. После игры с обоими, кажется, что 'Object.create (Rectangle.prototype)' является более чистым способом делать вещи, потому что вы 1) Не нужно вызывать конструктор дополнительное время и 2) у вас нет прототипа свойства, затененные объектами подтипа (при использовании 'new', height и width добавляются в 'Square.prototype', который затем затеняется this.height и this.width на конструкторе Square) –

+0

@MattHintzke IMO только' Опция Object.create() 'действительна. –

+1

@MattHintzke Это чище и менее подвержено ошибкам.'new' для создания прототипов эффективно устарел, даже если есть крайние случаи, когда он работает одинаково. – Bergi

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