Javascript: почему «this» внутри закрытой функции относится к глобальной области видимости? - PullRequest
16 голосов
/ 13 марта 2012

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

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();

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

Ответы [ 4 ]

35 голосов
/ 13 марта 2012

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

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

1 голос
/ 13 марта 2012

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

f.apply(this);
1 голос
/ 13 марта 2012

Объем всех функций: 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();
}
1 голос
/ 13 марта 2012

Причина, по которой вы вызываете 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();
...