Прототипы в JavaScript

Прототипы в JavaScript

Так как JavaScript это динамический язык, вы можете добавлять новые свойства к объекту в любое время, как показано ниже.

function Student() {
  this.name = 'John';
  this.gender = 'M';
}

var studObj1 = new Student();
studObj1.age = 15;
alert(studObj1.age); // Результат: 15

var studObj2 = new Student();
alert(studObj2.age); // Результат: undefined

Как видно из приведенного выше примера, свойство age добавлено к экземпляру studObj1. Однако экземпляр studObj2 не будет иметь свойства age, поскольку он определен только для экземпляра studObj1.

Так что же делать, если мы хотим добавить новые свойства на более позднем этапе к функции, которая будет использоваться всеми экземплярами?

Ответ - обратиться к прототипу.

Что такое прототип

Прототип - это объект, который по умолчанию связан со всеми функциями и объектами в JavaScript, где свойство prototype функции доступно и модифицируемо, а свойство prototype объекта (он же атрибут) не отображается.

Каждая функция включает объект-прототип по умолчанию.

Объект-прототип - это специальный тип объекта, к которому могут быть добавлены дополнительные свойства, которые будут общими для всех экземпляров его функции конструктора.

Итак, используйте свойство prototype функции в вышеприведенном примере, чтобы добавить свойство age для всех объектов, как показано ниже.

function Student() {
  this.name = 'John';
  this.gender = 'M';
}

Student.prototype.age = 15;

var studObj1 = new Student();
alert(studObj1.age); // Результат: 15

var studObj2 = new Student();
alert(studObj2.age); // Результат: 15

Каждый объект, который создается с использованием буквального синтаксиса или синтаксиса конструктора с ключевым словом new, включает свойство __proto__, которое указывает на объект-прототип функции, создавшей этот объект.

Вы можете отлаживать и видеть свойство prototype объекта или функции в инструменте разработчика Chrome или Firefox. Рассмотрим следующий пример.

function Student() {
  this.name = 'John';
  this.gender = 'M';
}

var studObj = new Student();

console.log(Student.prototype); // Результат: object
console.log(studObj.prototype); // Результат: undefined
console.log(studObj.__proto__); // Результат: object

console.log(typeof Student.prototype); // Результат: object
console.log(typeof studObj.__proto__); // Результат: object

console.log(Student.prototype === studObj.__proto__ ); // Результат: true

Как видно из приведенного выше примера, к свойству prototype функции можно получить доступ с помощью <имя-функции> .prototype. Однако объект (экземпляр) не предоставляет свойство prototype, вместо этого вы можете получить к нему доступ, используя __proto__.

Прототип объекта

Как упоминалось ранее, свойство прототипа объекта невидимо. Используйте метод Object.getPrototypeOf(obj) вместо __proto__ для доступа к объекту-прототипу.

function Student() {
  this.name = 'John';
  this.gender = 'M';
}

var studObj = new Student();

Student.prototype.sayHi = function(){
  alert("Hi");
};

var studObj1 = new Student();
var proto = Object.getPrototypeOf(studObj1); // Возвращает прототип объекта Student

alert(proto.constructor); // Возвращает функцию Student

Объект прототипа включает в себя следующие свойства и методы.

Свойства:

constructor Возвращает функцию, которая создала экземпляр.
__proto__ Это невидимое свойство объекта. Он возвращает объект-прототип функции, на которую он ссылается.

Методы:

hasOwnProperty() Возвращает логическое значение, указывающее, содержит ли объект указанное свойство как прямое свойство этого объекта и не унаследованое через цепочку прототипов.
isPrototypeOf() Возвращает логическое указание, находится ли указанный объект в цепочке прототипов объекта, для которого вызывается этот метод.
propertyIsEnumerable() Возвращает логическое значение, которое указывает, является ли указанное свойство enumerable или нет.
toLocaleString() Возвращает строку в локальном формате.
toString() Возвращает строку.
valueOf Возвращает примитивное значение указанного объекта.

Chrome и Firefox обозначают прототип объекта как __proto__, который является публичной ссылкой, тогда как внутри он ссылается как [[Prototype]]. Internet Explorer ниже версии 11 не включает __proto__.
Метод getPrototypeOf() стандартизирован начиная с ECMAScript 5 и доступен начиная с IE 9.

Изменение прототипа

Как упоминалось выше, каждый прототип объекта связан с объектом-прототипом функции. Если вы измените прототип функции, то только новый объект будет связан с измененным прототипом. Все остальные существующие объекты по-прежнему будут ссылаться на старый прототип функции. Следующий пример демонстрирует этот сценарий.

function Student() {
  this.name = 'John';
  this.gender = 'M';
}

Student.prototype.age = 15;

var studObj1 = new Student();
alert('studObj1.age = ' + studObj1.age); // 15

var studObj2 = new Student();
alert('studObj2.age = ' + studObj2.age); // 15

Student.prototype = { age : 20 };

var studObj3 = new Student();
alert('studObj3.age = ' + studObj3.age); // 20

alert('studObj1.age = ' + studObj1.age); // 15
alert('studObj2.age = ' + studObj2.age); // 15

Использование прототипов

Прототип объекта используется движком JavaScript в двух случаях:
для поиска свойств и методов объекта;
для реализации наследования в JavaScript.

function Student() {
  this.name = 'John';
  this.gender = 'M';
}

Student.prototype.sayHi = function(){
  alert("Hi");
};

var studObj = new Student();
studObj.toString();

В приведенном выше примере метод toString() не определен в Student, тогда как и где он находит toString()?

Прежде всего, движок JavaScript проверяет, подключен ли метод toString() к studObj. Если он не находит его там, то использует ссылку __proto__ в StudObj, которая указывает на объект-прототип функции Student. Если он все еще не может найти его там, он поднимается в иерархии и проверяет объект-прототип функции Object, потому что все объекты унаследованы от класса Object в JavaScript, и ищет метод toString(). Таким образом, он находит метод toString () в объекте-прототипе функции Object, и поэтому мы можем вызвать studObj.toString().

Оставьте первый комментарий

Оставить комментарий

Ваш электронный адрес не будет опубликован.


*