04. Объекты

Плюсы и минусы JavaScript

В JavaScript работает практически все, что не напишешь! В этом плюс языка — его гибкость, базирующаяся на контекстно зависимой семантике. Но в этом и минус, особенно для новичков: часто код работает совсем не так, как предполагает начинающий писатель.

Пример 1


var x = "0";
if (x) x++; // x равен 1 

Пример 2


var x = "0";
if (-x) x++; // x равен "0" 

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

В функции-конструкторе JavaScript нет никакой магии — это обычная функция, как и все остальные. Особый смысл функция получает только в сочетания с оператором new, который создаёт пустой объект и передаёт ссылку на него в качестве неявного аргумента this:


var rect = new Rectangle(2,3); // Создан объект rect класса Rectangle

Этот код работает следующим образом:

  1. Оператор new создает пустой объект {} и передает ссылку на него в функцию Rectangle.
  2. Функция Rectangle создает в пустом объекте свойства width и height и присваивает этим свойствам соответственно значения 2 и 3.

А что будет, если мы опустим оператор new?:


var rect = Rectangle(2,3); 

Функция Rectangle не возвращает никакого значения, поэтому переменная rect после такого присваивания сохранит значение undefined (как при простом описании var rect), но возникнут другие интересные последствия.

Ключевое слово this в Rectangle теперь относится к глобальному объекту window. Значит, функция Rectangle создаёт в этом объекте свойства width и height и присваивает этим свойствам соответственно значения 2 и 3. В этом легко убедиться, запустив следующий код:


function Rectangle(width,height) // Функция-конструктор
{
  this.width  = width;
  this.height = height;
}
var rect = Rectangle(2,3); 
alert(rect);          // undefined
alert(window.width);  // 2
alert(window.height); // 3

При работе с глобальным объектом window ссылку на него можно опускать, поэтому:

Функция-конструктор, как правило, не возвращает никакого значения. Но это обычная функция. Ничто не мешает в ней записать инструкцию return:


function Rectangle(width,height) 
{
  this.width  = width;
  this.height = height;
  return width + height;
}
var rect = Rectangle(2,3); 
alert(rect);   // 5
alert(width);  // 2
alert(height); // 3

Если конструктор возвращает значение элементарного типа и используется в контексте оператора new, возвращаемое значение просто теряется.


function Rectangle(width,height)
{
  this.width  = width;
  this.height = height;
  return width + height;
}
var rect = new Rectangle(2,3); 
alert(rect.width);    // 2
alert(rect.height);   // 3
alert(window.width);  // undefined
alert(window.height); // undefined

А если конструктор возвращает объект, то этот объект становится значением выражения new конструктор.


function Rectangle(width,height) // Функция-конструктор
{
  this.width  = width;
  this.height = height;
  return {x:20,y:30};
}
var rect = new Rectangle(2,3); 
alert(rect.width);    // undefined
alert(rect.height);   // undefined
alert(rect.x);        // 20
alert(rect.y);        // 30
alert(window.width);  // undefined
alert(window.height); // undefined