Понимание prototypal наследование в JavaScript

используйте этот код, это будет работать лучше;

<android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_alignParentBottom="true"
        android:layout_margin="16dp"
        app:backgroundTint="#f9fcfc"

        android:src="@drawable/chat_float"
        tools:targetApi="lollipop" />
170
задан trincot 1 September 2018 в 09:58
поделиться

4 ответа

Эти два блока отличаются тем, что в первом примере Drive () будет существовать только один раз, тогда как при втором подходе Drive () будет существует для каждого экземпляра (Каждый раз, когда вы выполняете new Car () , функция drive () будет создаваться снова). Или, по-другому, сказано, что первый использует прототип для хранения функции, а второй - конструктора. Поиск функций - это конструктор, а затем прототип. Итак, при поиске Drive () он находит его независимо от того, находится ли он в конструкторе или в прототипе. Использование прототипа более эффективно, потому что обычно функция требуется только один раз для каждого типа.

Вызов new в javascript автоматически устанавливает конструктор в прототипе. Если вы перезаписываете прототип, вам нужно установить конструктор вручную.

Наследование в javascript не имеет ничего общего с super . Поэтому, если у вас есть подкласс, единственный шанс вызвать суперконструктор - это его имя.

82
ответ дан 23 November 2019 в 20:48
поделиться

Я не уверен на 100%, но я считаю, что разница в том, что второй пример просто дублирует содержимое класса Car в объект SuperCar, а первый связывает прототип SuperCar с Car класс, так что изменения во время выполнения в классе Car влияют также на класс SuperCar.

1
ответ дан 23 November 2019 в 20:48
поделиться

Чтобы добавить к ответу Норберта Хартла , SuperCar.prototype .constructor не нужен, но некоторые люди используют его как удобный способ получить функцию построения объекта (в данном случае объекты SuperCar).

Как раз из первого примера, Car.call (this, name) находится в функции конструктора SuperCar, потому что когда вы делаете это:

var mySuperCar = new SuperCar("SuperCar");

Вот что делает JavaScript:

  1. Создается новый пустой объект.
  2. Внутренний прототип нового объекта установлен на Car.
  3. Выполняется функция конструктора SuperCar.
  4. Готовый объект возвращается и устанавливается в mySuperCar.

Обратите внимание, как JavaScript не вызывал Car вместо вас. Поскольку прототипы остаются такими, какие они есть, любое свойство или метод, которые вы не устанавливаете для SuperCar, будут найдены в Car. Иногда это хорошо, например, у SuperCar нет метода Drive, но он может использовать тот же метод Drive, поэтому все SuperCar будут использовать один и тот же метод Drive. В других случаях вы не Я не хочу делиться, как будто каждая суперкара имеет собственное имя. Так как же присвоить каждому суперкару собственное имя? Вы можете установить this.Name внутри функции конструктора SuperCar:

function SuperCar(name){
    this.Name = name;
}

Это работает, но подождите секунду. Разве мы не сделали то же самое в конструкторе автомобилей? Не хочу повторяться. Поскольку Car уже задает имя, давайте просто назовем его.

function SuperCar(name){
    this = Car(name);
}

Ой, вы никогда не захотите изменять специальную ссылку на объект this . Помните 4 шага? Держитесь за этот объект, который предоставил вам JavaScript, потому что это единственный способ сохранить ценную внутреннюю связь прототипа между вашим объектом SuperCar и Car. Так как же установить Name, не повторяя себя и не выбрасывая наш свежий объект SuperCar. JavaScript потратил столько особых усилий, чтобы подготовить нас?

Две вещи. Один: значение это гибкое. Два: Автомобиль - это функция. Можно вызвать Car не с помощью нетронутого, свежего экземпляра объекта, а вместо этого, скажем, с помощью объекта SuperCar. Это дает нам окончательное решение, которое является частью первого примера в вашем вопросе:

function SuperCar(name){
    Car.call(this, name);
}

Как функция, Car может быть вызван с помощью метода вызова функции , который меняет значение ] this внутри Car к экземпляру SuperCar, который мы создаем. Престо! Теперь каждый SuperCar получает собственное свойство Name.

В заключение, Car.call (this, name) в конструкторе SuperCar дает каждому новому объекту SuperCar собственное уникальное свойство Name, но без дублирования кода. это уже в Машине.

Прототипы не страшны, если вы их понимаете, но они ' re совсем не похожа на классическую модель ООП класса / наследования. Я написал статью о концепции прототипов в JavaScript . Он написан для игрового движка, использующего JavaScript, но это тот же движок JavaScript, что и Firefox, поэтому все должно быть актуальным. Надеюсь, это поможет.

140
ответ дан 23 November 2019 в 20:48
поделиться

Norbert, you should note that your first example is pretty much what Douglas Crockford calls pseudoclassical inheritance. Something things to note about this:

  1. You will call the Car constructor twice, once from the SuperCar.prototype = new Car() line and the other from the "constructor stealing" line Car.call(this...you can create a helper method to inherit prototypes instead and your Car constructor will only have to run once making the setup more efficient.
  2. The SuperCar.prototype.constructor = SuperCar line will allow you to use instanceof to identify the constructor. Some folks want this others just avoid using instanceof
  3. Reference vars like: var arr = ['one','two'] when defined on the super (eg Car) will get shared by ALL instances. This means inst1.arr.push['three'], inst2.arr.push['four'], etc., will show up for all instances! Essentially, static behavior that you probably don't want.
  4. You second block defines the fly method in the constructor. This means for every time that it's called, a "method object" will be created. Better to use a prototype for methods! You CAN however keep it in the constructor if you'd like - you just need to guard so you only actually initialize the prototype literal once (pseudo): if (SuperCar.prototype.myMethod != 'function')...then define your prototype literal.
  5. 'Why call Car.call(this, name)....': I don't have time to look carefully at your code so I may be wrong but this is usually so that each instance can keep it's own state to fix the 'staticy' behavior issue of prototype chaining that I described above.

Lastly, I'd like to mention that I have several examples of TDD JavaScript Inheritance code that works here: TDD JavaScript Inheritance Code and Essay I'd love to get your feedback as I'm hoping to improve it and keep it open source. The goal is to help classical programmers get up to speed with JavaScript quickly and also supplement the study both Crockford and Zakas books.

8
ответ дан 23 November 2019 в 20:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: