04. Объекты

Объектно ориентированное программирование

Сравним работу с объектами в языках C++ и JavaScript.

Объектно ориентированный язык C++ взят только потому, что мне он больше знаком.

В языке C++ есть ключевое слово class. Например, можно создать класс Rectangle:


// Описание класса Rectangle (прямоугольник)
// Инициализирует в экземпляре класса переменные width и height
// Создаёт функцию square() -- вычисление площади 
class Rectangle
{
  public:
  int width;  // Это переменная-член класса 
  int height; // Это переменная-член класса
  int square() {return width*height}; // Это функция-член класса
}

Описание класса не представляет собой какой-либо конкретный объект, а является шаблоном («документацией») для создания объектов данного типа. Слово Rectangle теперь становится обозначением нового типа данных (наряду с int). Можно написать:


int z;
Rectangle rect;  // Создан объект rect. В этот объект скопированы 
                 // переменные width и height, а также функция square
rect.width =  2; // Инициализирована переменная width в объекте rect
rect.height = 3; // Инициализирована переменная height в объекте rect
z = rect.square(); // Равно 6

В C++ можно описать функцию-конструктор. Делается это так:


// Описание класса Rectangle (прямоугольник)
// Инициализирует в экземпляре класса переменные width и height
// Создаёт функцию square() -- вычисление площади 
// Описывает функцию-конструктор
class Rectangle
{
  public:
  int width;  // Это переменная-член класса 
  int height; // Это переменная-член класса
  Rectangle(int x, int y) // Функция-конструктор класса 
  {                       // Её имя совпадает с именем класса
    width  = x;
    height = y;
  }
  int square() {return width*height}; // Это функция-член класса
}

Теперь можно написать:


int z;
Rectangle rect(2,3); // Создан объект rect. Переменные объекта 
                     // инициализированы при помощи функции-конструктора
z = rect.square();   // Равно 6

Что характерно, функции, описанные внутри класса доступны только для объектов этого класса.

Как мы видели, функции JavaScript более независимы: они не принадлежат никакому объекту (независимо от того, где описаны). Они связываются с объектом только в момент выполнения при помощи ключевого слова this. Ключевое слово this обозначает объект, в контексте которого вызывается функция. Если вызов функции явно не связан с объектом, то таким объектом выступает глобальный объект window.

В C++ ключевое слово this имеет другой смысл. Считается, что в функциях-членах класса всегда присутствует неявный аргумент this, который ссылается на объект (экземпляр класса), в котором эта функции вызывается.

В JavaScript this ни на что не ссылается во время описания! Ключевое слово this в JavaScript приобретает конкретный смысл только во время вызова функции, и связывается с тем объектом, в контексте которого функция работает.

Ещё раз посмотрите, заданы два объекта разных типов:


var rect = { x:10, y:20, square:sq };
var cube = { x:2, y:3, z:16, square:sq };

И одна функция:


function sq() {return this.x*this.y;}

Ключевое слово this в этой функции ни на что не ссылается, пока функция не будет вызвана.


rect.sq() // Сейчас this ссылается на объект rect
cube.sq() // Сейчас this ссылается на объект cube
sq()      // Сейчас this ссылается на объект window

Итак, в C++ (и других подобных языках) есть классы — шаблоны, содержащие «документацию» на объекты. Для описания классов предусмотрено специальное ключевое слово class. Имя созданного класса используется наравне с ключевым словом, описывающим тип данных (таким как int) для создания объектов — экземпляров класса.

В JavaScript нет «настоящих» классов, но можно строить функции-конструкторы с описаниями шаблонов объектов. Создаются объекты при помощи функции-конструктора и оператора new.

Хотя в JavaScript нет настоящих классов, для удобства изложения будем называть классом функцию, используемую как конструктор, а объекты, созданные с её помощью — экземплярами класса или просто объектами.