04. Объекты

Что такое this в JavaScript

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

Пусть задано следующее определение функции:


function sq() {return this.x*this.y;}
и два объекта:
var rect = { x:10, y:20, square:sq };
var cube = { x:2, y:3, z:16, square:sq };

В каждом из этих объектах свойство square ссылается на одну и ту же функцию sq. Посмотрим, что будет означать ключевое слово this, записанное внутри функции sq.


rect.square()  // Равно 200
               // Вызывается функция sq(), в ней this 
               // ссылается на объект rect  

cube.square()  // Равно 6
               // Вызывается функция sq(), в ней this 
               // ссылается на объект cube  

Ничего не изменится, если функцию sq задать в виде литерала внутри первого объекта. При вызове в контексте второго объекта this внутри этой функции будет ссылаться не на первый, а на второй объект, в контексте которого выполняется вызов:


var rect = { x:10, y:20, square:function () {return this.x*this.y;} };
var cube = { x:2, y:3, z:16, square:rect.square };

rect.square()  // Равно 200
               // Здесь this относится к rect
cube.square()  // Равно 6
               // Здесь this относится к cube, хотя функция 
               // определена в rect

Видим, насколько JavaScript является контекстно-зависимым языком. В других объектно-ориентированных языках методы жёстко привязаны к объектам, внутри которых они заданы, и не могут работать с другими объектами.

Проведем интересный эксперимент. Пусть функция описана следующим образом:


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

Какой результат будет получен при запуске в котором нет явной связи с каким либо объектом? Проверим:


var x = sq();  // x равно NaN

Дело вот в чём. Функции в JavaScript всегда работают в контексте какого либо объекта. Если объект явно не задан, то таким объектом выступает глобальный объект window (окно браузера), если JavaScript работает в браузере.

Значит, this относится именно к window и x и y — переменные этого глобального объекта. Мы эти переменные не вводили. Но в JavaScript есть правило: если переменная не описана явно при помощи инструкции var, она считается глобальной и автоматически описывается (создаётся) в глобальном объекте window.

Таким образом, результат вызова sq() объясняется следующим образом.

  1. Создаются глобальные переменные с именами x и y.
  2. Результат умножения x*y равен NaN, так как значения переменных равны undefined (undefined*undefined есть NaN)

А вот в таком коде будет получен «нормальный» числовой результат:


function sq() {return this.x*this.y;}
var x=7;
var y=8;
var z = sq(); // Равно 56

О глобальном объекте window, в контексте которого всегда работает код на JavaScript, и о глобальных переменных, которые на самом деле являются свойствами объекта window, мы поговорим подробнее, когда будем присматриваться к областям видимости переменных и обсуждать работу функций (заметки 5, 7, 8 и 9).