Javascript: почему "this" внутри частной функции относится к глобальной области?

Рассмотрим следующий код:

function A() {}    

A.prototype.go = function() {
    console.log(this); //A { go=function()}

    var f = function() {
         console.log(this);  //Window              
    };

    f();
}

var a = new A();
a.go();

Почему функция 'this' внутри функции "f" относится к глобальной области? Почему это не область действия "А"?

Ответы

Ответ 1

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

Глобальная область

this;

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

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

foo();

Здесь this снова будет ссылаться на глобальный объект.

ES5 Примечание: В строгом режиме существует глобальный случай больше. this вместо этого будет иметь значение undefined в этом случае.

Вызов метода

test.foo(); 

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

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

new foo(); 

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

Явная настройка this

function foo(a, b, c) {}

var bar = {};
foo.apply(bar, [1, 2, 3]); // array will expand to the below
foo.call(bar, 1, 2, 3); // results in a = 1, b = 2, c = 3

При использовании методов call или apply Function.prototype значение this внутри вызываемой функции получает явно установленный первый аргумент соответствующего вызова функции.

В результате в приведенном выше примере случае метода применяется не, а this внутри foo будет установлено значение bar.

Примечание. this не может использоваться для ссылки на объект внутри Objectбуквальный. Таким образом, var obj = {me: this} будет не привести к me, ссылаясь на obj, так как this ограничивается только одним из пяти перечисленных случаев.

Общие ошибки

В то время как большинство из этих случаев имеет смысл, первое должно рассматриваться как другое неправильный дизайн языка, поскольку он никогда не имеет практического применения.

Foo.method = function() {
    function test() {
        // this is set to the global object
    }
    test();
}

Общим заблуждением является то, что this внутри test относится к foo; пока в факт, он не.

Чтобы получить доступ к foo из test, необходимо создать локальная переменная внутри method, которая ссылается на foo.

Foo.method = function() {
    var that = this;
    function test() {
        // Use that instead of this here
    }
    test();
}

that - это просто нормальное имя переменной, но оно обычно используется для ссылки на внешний this. В сочетании с закрытием он также может для передачи значений this.

Назначение методов

Еще одна вещь, которая работает не в 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 теперь будет ссылаться на это очень случай.

Отказ от ответственности: Shamelessy украден из моих собственных ресурсов в http://bonsaiden.github.com/JavaScript-Garden/#function.this

Ответ 2

Причина, по которой вы вызываете f как function, а не method. При вызове функции this устанавливается window во время выполнения целевого

// Method invocation.  Invoking a member (go) of an object (a).  Hence 
// inside "go" this === a
a.go();

// Function invocation. Invoking a function directly and not as a member
// of an object.  Hence inside "f" this === window
f(); 

// Function invocation. 
var example = a.go;
example();

Ответ 3

Объем всех функций window.

Чтобы обойти это, вы можете сделать это:

function A() {}    

A.prototype.go = function() {
    var self = this;
    console.log(self); //A { go=function()}
    var f = function() {
         console.log(self);  //A { go=function()}           
    };

    f();
}

Ответ 4

Потому что функция f() не вызывается без ссылки на объект. Попробуйте,

f.apply(this);