Конспект JS-course

Свои объекты: конструкторы и методы

Источник: http://learn.javascript.ru/object-methods

Свои методы объектов

При объявлении в объект можно записать функцию. Она становится его методом, например:

var user = {
  name: 'Василий',

  // метод
  sayHi: function() {
    alert('Привет!');
  }
};

// Вызов метода
user.sayHi();

Доступ к объекту через this

Для полноценной работы метод должен иметь доступ к данным объекта. В частности, вызов user.sayHi() может захотеть вывести имя пользователя.

Для доступа к объекту из метода используется ключевое слово this. Значением this является объект, в контексте которого вызван метод, например:

var user = {
  name: 'Василий',

  sayHi: function() {
    alert(this.name);
  }
};
user.sayHi();

Здесь при выполнении функции user.sayHi() в this будет храниться ссылка на текущий объект user. Использование this гарантирует, что функция работает именно с тем объектом, в контексте которого вызвана.

Через this можно обратиться к любому свойству объекта, а при желании и передать его куда-то:

var user = {
  name: 'Василий',
  sayHi: function() {
    showName(this); // передать текущий объект в showName
  }
};

function showName(obj) {
  alert( obj.name );
}

user.sayHi(); // Василий

Функция - конструктор, «new»

Обычный синтаксис {...} позволяет создать один объект. Но зачастую нужно создать много однотипных объектов.

Для этого используют функции, запуская их при помощи специального оператора new.

Конструктором становится любая функция, вызванная через new.

Например:

function Animal(name) {
  this.name = name;
  this.canWalk = true;
}

var animal = new Animal("ёжик");

Любую функцию можно вызвать при помощи new. При этом она работает несколько иным образом, чем обычно:

  1. Автоматически создается новый, пустой объект.
  2. Специальное ключевое слово this получает ссылку на этот объект.
  3. Функция выполняется. Как правило, она модифицирует this, добавляет методы, свойства.
  4. Возвращается this.

Так что результат выполнения примера выше — это объект:

animal = {
  name: "ёжик",
  canWalk: true
}

О создаваемом объекте говорят, что это «объект класса (или типа) Animal».

Если функция явно возвращает объект, то будет возвращён он, а не this.

Названия функций, которые предназначены создавать объекты, как правило, начинают с большой буквы.

Создание методов в конструкторе

Использование функций для создания объекта дает большую гибкость. Можно передавать функции свойства создаваемого объекта и параметры, определяющие как его создавать.

Например, функция User(name) создает объект с заданным значением свойства name и методом sayHi:

function User(name) {
  this.name = name;

  this.sayHi = function() {
    alert("Моё имя: " + this.name);
  };
}

Приватные свойства

Локальные переменные функции-конструктора, с одной стороны, доступны вложенным функциям, с другой — недоступны снаружи.

В объектно-ориентированном программировании это называется «приватный (private) доступ».

Например, в коде ниже к name имеет доступ только метод say. Со стороны объекта, после его создания, больше никто не может получить name.

function User(name) {
  this.say = function(phrase) {
    alert(name + ' сказал: ' + phrase);
  };
}

var user = new User('Вася');

Если бы name было свойством this.name — можно было бы получить его как user.name, а тут — локальная переменная. Приватный доступ.

Замыкания никак не связаны с this.

Доступ через замыкание осуществляется к локальной переменной, находящейся «выше» по области видимости.

А this содержит ссылку на «текущий» объект — контекст вызова, и позволяет обращаться к его свойствам. С локальными переменными это никак не связано.

Приватные свойства можно менять, например ниже метод this.upperCaseName() меняет приватное свойство name:

function User(name) {
  this.upperCaseName = function() {
    name = name.toUpperCase(); // <-- изменяет name из User
  };

  this.say = function(phrase) {
    alert(name + ' сказал: ' + phrase); // <-- получает name из User
  };

}

var user = new User('Вася');

user.upperCaseName();
user.say("Да здравствует ООП!") // ВАСЯ сказал: Да здравствует ООП!

Вы помните, в главе Замыкания, функции изнутри мы говорили о скрытых ссылках [[Scope]] на внешний объект переменных? В этом примере user.upperCaseName.[[Scope]] и user.say.[[Scope]] как раз ссылаются на один и тот же объект LexicalEnvironment, в контексте которого они были созданы. За счёт этого обе функции имеют доступ к name и другим локальным переменным.

Все переменные конструктора User становятся приватными, так как доступны только через замыкание, из внутренних функций.

Итого

У объекта могут быть методы:

  • Свойство, значение которого - функция, называется методом объекта и может быть вызвано как obj.method(). При этом объект доступен как this.

Объекты могут быть созданы при помощи функций-конструкторов:

  • Любая функция может быть вызвана с new, при этом она получает новый пустой объект в качестве this, в который она добавляет свойства. Если функция не решит возвратить свой объект, то её результатом будет this.
  • Функции, которые предназначены для создания объектов, называются конструкторами. Их названия пишут с большой буквы, чтобы отличать от обычных.