В JavaScript есть несколько способов создания экземпляра объекта и несколько других способов создания наследования. В этом посте я рассмотрю функциональное, прототипное и псевдоклассическое наследование и, надеюсь, сделаю этот процесс немного проще для понимания.
Одна важная вещь, которую нужно знать о JavaStript, заключается в том, что каждый созданный объект наследует свойства и методы от своего прототипа. Вы можете добавить к своему объекту объекты-прототипы, которые будут организованы в цепочку прототипов . В верхней части этой цепочки вы найдете Object.prototype, объект, который имеет такие свойства и методы, как: — .hasOwnProperty() и .toString() — к ним может получить доступ любой объект, что означает, что он является частью области действия объекта в JavaScript.
.hasOwnProperty() — возвращает логическое значение, указывающее, содержит ли этот объект прямое свойство, не унаследованное через цепочку прототипов.
.toString() — возвращает строковое представление этого объекта.
Если вы хотите это проверить:
// to open the console on your browser type command + option + j // inside the console type Object.prototype // press enter
Как вы можете видеть, этот объект имеет ряд методов и свойств, которые можно использовать для любого объекта в JavaScript, независимо от того, как вы его реализуете, если, конечно, реализация правильная!!!
Как работает цепочка прототипов в javaScript?!
Допустим, вы создаете переменную obj, связанную с объектом:
var obj = { ‘a’: 2}; obj.toString() // => ‘[object Object]’
Это работает следующим образом: интерпретатор заглянет внутрь этой области объекта и увидит, объявлен ли там метод .toString(), мы только что создали obj и просто передали ключ : 'a 'и значение: 2, поэтому интерпретатор не найдет этотметод.Поэтому интерпретатор поднимается на один уровень в цепочке в поисках этого конкретного метода, поскольку это простой объект, у него нет очень интересной цепочки прототипов, поэтому интерпретатор переходит из области видимости 'obj' в область Object.prototype, и там он найдет .toString(), возвращающий obj в виде строки вместо undefined.
Теперь давайте поговорим о том, как создавать объекты, которые могут создавать свои собственные методы-прототипы и свойства для добавления в цепочку:
Перво-наперво, давайте создадим объект вручную:
// create an empty object const lara = {}; // now with the object we can assign properties and values to it lara.firstName = ‘Lara’; lara.lastName = ‘Ismael’ lara.age = 29; lara.country = ‘Brasil’; lara.sayName = (firstName, lastName) => console.log(`${ firstName } ${ lastName }`);
Теперь, когда у нас есть этот объект с моей информацией, что бы мы сделали, если бы я захотел создать последовательность объектов с такой же структурой, как этот, но с другими значениями, мы могли бы сделать это вручную, но это может занять много времени, в зависимости от сколько объектов вы создаете, также мы хотим не повторяться при написании кода…
Так как же нам обойти это повторяющееся движение создания объектов???
— Введите экземпляры Объекта:
1- Функциональная реализация:
// create a function to instantiate different objects with the same structure var peoplesInfo = (firstName, lastName, age, country) => { return { firstName: this.firstName, lastName: this.lastName, age: this.age, country: this. country, sayName: (firstName, LastName) => console.log(`${ firstName } ${ LastName }`); } }
Эта функция использует ключевое слово 'this', и я не буду вдаваться в подробности того, как она работает, но для понимания цели в этом случае 'this' привязано к аргументам, которые вы будете передавать при вызове функции.
Теперь это намного лучше, чем создание объекта нескольких людей… Помните, НЕ ПОВТОРЯЙТЕСЬ СЕБЯ.
// here we create 2 people using the function we created above var Lara = peoplesInfo( ‘Lara’, ‘Ismael’, 29, ‘Brasil’); var Aly = peoplesInfo( ‘Aly’, ‘Smith’, 33, ‘USA’);
И вот мы только что решили проблему повторения…
Некоторые другие преимущества создания функциональных экземпляров заключаются в том, что у вас могут быть закрытые переменные, ЕСЛИ вы правильно используете свои функции закрытия. Это то, что предлагает только функциональная реализация. С другой стороны, здесь есть повторение, потому что каждый раз, когда мы создаем новый объект с помощью этой функции, мы создаем метод sayName().
2- Прототип:
// create a function to instantiate different objects with the same structure we use the create method var peoplesInfo = (firstName, lastName, age, country) => { var result = Object.create( peoplesInfo.prototype); result .firstName = firstName; result .lastName = lastName; result .age = age; result .country = country; return result; }; peoplesInfo.prototype.sayName: (firstName, lastName) => console.log(`${ firstName } ${ lastName }`); // now we can create people: var Lara = new peoplesInfo( ‘Lara’, ‘Ismael’, 29, ‘Brasil’); var Aly = new peoplesInfo( ‘Aly’, ‘Smith’, 33, ‘USA’);
Приведенный выше код работает следующим образом: переменная result может быть делегирована peoplesInfo.prototype и в случае поиска этого объекта, когда peoplesInfo должен возвращать undefined, результирующая переменная имеет метод sayName() в своей цепочке прототипов, поэтому интерпретатор сможет найти его и вместо возврата undefined он фактически сможет ссылаться на функцию и полное имя console.log.
Просто чтобы быть предельно ясным, когда вы вызываете peoplesInfo.sayName(), интерпретатор проверяет sayName внутри объекта peoplesInfo и не находит его, в этот момент он делегирует прототип подбородка, поиск sayName() и возврат его.
3- Псевдоклассическая реализация:
// create a function to instantiate different objects with the same structure and we can omit the create method var peoplesInfo = (firstName, lastName, age, country) => { // no need for this anymore: /* var result = Object.create( peoplesInfo.prototype); */ this.firstName = firstName; this.lastName = lastName; this.age = age; this.country = country; // no need for this anymore: /* return result; */ }; peoplesInfo.prototype.sayName: (firstName, lastName) => console.log(`${ firstName } ${ lastName }`); // now we can create people: var Lara = new peoplesInfo( ‘Lara’, ‘Ismael’, 29, ‘Brasil’); var Aly = new peoplesInfo( ‘Aly’, ‘Smith’, 33, ‘USA’);
Давайте начнем знакомство с ключевым словом new, которое устанавливает новый объект в соответствии со структурой, созданной в peoplesInfo(). peoplesInfo.prototype.sayName() — это то, что будет первым в цепочке прототипов, если вызов this не удался. примером этого может быть, когда мы вызываем this.sayName(), браузер будет искать в функции peoplesInfo sayName(), не найдя ее, интерпретатор перейдет к следующий объект-прототип в цепочке, и он находит его там и console.logs this.sayName().
Это дает нам некоторую гибкость внутри нашей функции и легкий доступ к ключевому слову'this'. Еще одна прелесть в том, что поскольку 'this' добавляется и возвращается автоматически, вы не можете должны использовать метод Object.create() или возвращать объект, javascript позаботится об этом за нас.
Здесь у вас есть три разных способа создания объекта, который может создавать экземпляры других объектов и передавать свои методы и свойства.
Теперь давайте рассмотрим конкретный случай наследования с использованием псевдоклассики:
// create your class var Person = function(name) { this.name = name; }; // create a method for your class Person.prototype.travelPlaces = function(destination) { return `${this.name} is walking to ${destination}!`; }; // create a subclass that inherits properties of Person class var FasterPerson = function(name, transportation) { // get all properties passed from Person Person.apply(this, arguments); // add the new properties specific to this subclass this.transportation = transportation; }; //now we create the prototype chain connection FasterPerson.prototype = Object.create(Person.prototype) // make the subclass a constructor FasterPerson.prototype.constructor = FasterPerson; // at this point we can use the function that we inherited from Person and add some more functionality to it FasterPerson.prototype.travelPlaces = function(destination, milesToDestination) { if (milesToDestination < 10) { return Person.prototype.travelPlaces.apply(this, arguments); } else { return `${this.name} using a ${transportation} is going to ${destination}!`; } };
Это все для этого поста…
Спасибо за прочтение, надеюсь было полезно!