Skip to content

Latest commit

 

History

History
92 lines (54 loc) · 5.72 KB

File metadata and controls

92 lines (54 loc) · 5.72 KB

Как работает this

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

1. Глобальная область видимости

this;

Когда мы используем this в глобальной области, она будет просто ссылаться на глобальный объект.

2. Вызов функции

foo();

Тут this также ссылается на глобальный объект.

ES5 Замечание: В strict-режиме теряется понятие глобальности, поэтому в этом случае this будет иметь значение undefined.

3. Вызов метода

test.foo();

В данном примере this ссылается на test.

4. Вызов конструктора

new foo();

Если перед вызовом функции присутствует ключевое слово new то данная функция будет действовать как конструктор. Внутри такой функции this будет указывать на новосозданный Object.

5. Переопределение this

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 будет ссылаться на этот самый экземпляр.