В JavaScript область ответственности специальной переменной this концептуально отличается от того, за что отвечает this в других языках программирования. Различают ровно пять вариантов того, к чему привязывается this в языке.
this;
Когда мы используем this в глобальной области, она будет просто ссылаться на глобальный объект.
foo();
Тут this также ссылается на глобальный объект.
ES5 Замечание: В strict-режиме теряется понятие глобальности, поэтому в этом случае
thisбудет иметь значениеundefined.
test.foo();
В данном примере this ссылается на test.
new foo();
Если перед вызовом функции присутствует ключевое слово new то данная функция будет действовать как конструктор. Внутри такой функции this будет указывать на новосозданный Object.
function foo(a, b, c) {}
var bar = {};
foo.apply(bar, [1, 2, 3]); // массив развернётся в a = 1, b = 2, c = 3
foo.call(bar, 1, 2, 3); // аналогично
Когда мы используем методы call или apply из Function.prototype, то внутри вызваемой функции this явным образом будет присвоено значение первого передаваемого параметра.
Исходя из этого, в предыдущем примере (строка с apply) правило #3 вызов метода не будет применёно, и this внутри foo будет присвоено bar.
Замечание:
thisнельзя использовать внутри литералов{}(Object) для ссылки на сам объект. Т.е. если мы напишемvar obj = {me: this}, тоmeне будет ссылаться наobj, посколькуthisприсваивается только по одному из пяти описанных правил.
Хотя большинство из примеров ниже наполнены глубоким смыслом, первый из них можно считать ещё одним упущением в самом языке, поскольку он вообще не имеет практического применения.
Foo.method = function() {
function test() {
// this ссылается на глобальный объект
}
test();
}
Распространенным заблуждением будет то, что this внутри test ссылается на Foo, но это не так.
Для того, чтобы получить доступ к Foo внутри функции test, необходимо создать локальную перменную внутри method, которая и будет ссылаться на Foo.
Foo.method = function() {
var that = this;
function test() {
// Здесь используем that вместо this
}
test();
}
Подходящее имя для переменной - that, его часто используют для ссылки на внешний this. В комбинации с замыканиями this можно пробрасывать в глобальную область, или в любой другой объект.
Замечание от перев. Кроме
thatтакже часто встречаютсяthis_,self_и другие варианты, но лучше принять для себяthatкак стандарт и тогда, возможно, все вокруг тоже будут им пользоваться.
Еще одной фичей, которая не работает в JavaScript, является создание псевдонимов для методов, т.е. присвоение метода объекта переменной.
var test = someObject.methodTest;
test();
Следуя первому правилу test вызывается как обычная функция; следовательно this внутри него больше не ссылается на someObject.
Хотя позднее связывание this на первый взгляд может показаться плохой идеей, но на самом деле именно благодаря этому работает наследование прототипов.
function Foo() {}
Foo.prototype.method = function() {};
function Bar() {}
Bar.prototype = Foo.prototype;
new Bar().method();
В момент, когда будет вызван method нового экземляра Bar, this будет ссылаться на этот самый экземпляр.