Оглавление

19.2. Прототипы

В    предыдущем    разделе    мы    определяли    метод    getModelO     внутри конструктора:

   function Cars(m, y) { // Конструктор объекта
      this.model = m;
      this.year = y;
      this.getModel = function() { // Метод
         return this.model;
      }
   }


Подобное решение не является эффективным. Предположим, необходимо составить массив, описывающий тысячу автомобилей. Свойства model и year в этом случае будут содержать разные значения, а вот метод getModel() во всех этих объектах один и тот же.
Использование прототипов позволяет определить метод вне конструктора. При создании объекта наследуются все свойства, которые имеются в прототипе. Таким образом, метод getModel() будет определен один раз, но будет наследоваться всеми экземплярами объекта.
Для добавления метода в прототип используется свойство prototype:

   function Cars(m, y) { // Конструктор объекта
      this.model = m;
      this.year = y;
   }
   Cars.prototype.getModel = function() {
      return this.model;
   }
   var car1 = new Cars("Москвич-412", 1978);
   window.alert(car1.getModel()); // "Москвич-412"
   var car2 = new Cars("ВАЗ-2109", 2002);
   window.alert(car2.getModel()); // "ВАЗ-2109"

Как уже говорилось, свойства, определенные в прототипе, наследуются всеми экземплярами. Таким образом, метод getModel() доступен для перебора в цикле for...in, а также успешно проверяется на наличие с помощью оператора in. Тем не менее метод hasOwnProperty() позволяет определить, что метод является унаследованным:

   if ("getModel" in car1) window.alert("Метод определен");
   else window.alert("Нет");
   // Выведет: "Метод определен"
   if (car1.hasOwnProperty("getModel"))
      window.alert("Метод определен");
   else window.alert("Нет");
   // Выведет: "Нет", так как метод унаследован

 

Любой созданный объект автоматически наследует свойства класса object. Например, при попытке вывести значение экземпляра объекта в диалоговом окне вызывается метод toStringO, который должен возвращать значение в виде строки. Для примера выведем текущее значение:

   var car1 = new Cars("Москвич-412", 1978);
   window.alert(car1);


В результате в диалоговом окне получим следующий результат:
    [object Object]
С помощью прототипов можно переопределить этот метод таким образом, чтобы выводилось нужное нам значение:

   Cars.prototype.toString = function() {
      return "Модель: " + this.model + " Год выпуска: " + this.year;
   }
   var car1 = new Cars("Москвич-412", 1978);
   window.alert(car1);


В результате в диалоговом окне получим следующий результат:
  

   Модель: Москвич-412 Год выпуска: 1978

 

При попытке произвести арифметическую операцию вызывается метод vaiueof(), который должен возвращать значение в виде числа. Для примера переопределим метод таким образом, чтобы он возвращал сколько лет автомобилю:

   Cars.prototype.valueOf = function() {
      return 2009 - this.year;
   }
   var car1 = new Cars("Москвич-412", 1978);
   window.alert(car1 * 1); // 31


Практически все встроенные объекты JavaScript (например, string, Array) имеют свойство prototype. С его помощью можно расширить возможности встроенных классов, например, добавить новый метод. В качестве примера добавим метод inArray () в класс Array. Этот метод будет производить поиск значения в массиве и возвращать индекс первого вхождения. Если вхождение не найдено, то метод вернет значение -1:

Array.prototype.inArray = function(elem) {
   for (var i=0, len=this.length; i<len; i++) {
      if (this[i]===elem) return i;
   }
   return -1;
}
var arr = [ 1, 2, 3, 4, 5, 1 ];
var pos = arr.inArray(5);
if (pos != -1) window.alert("Индекс элемента " + pos);
else window.alert("Не найдено");
// Выведет: "Индекс элемента 4"




Примечания:
  • Не рекомендуется расширять возможности встроенных классов, так как другие программисты могут прийти в недоумение, увидев новый метод.
Комментарии принадлежат их авторам. Мы не несем ответственности за их содержание.
Отправитель Нити