jQuery/JavaScript това объркване на указателя

Поведението на "this", когато се извиква функция bar, ме озадачава. Вижте кода по-долу. Има ли някакъв начин да уредите „това“ да бъде обикновен екземпляр на стар js обект, когато bar се извиква от манипулатор на кликване, вместо да бъде html елемент?

// a class with a method

function foo() {

    this.bar();  // when called here, "this" is the foo instance

    var barf = this.bar;
    barf();   // when called here, "this" is the global object

    // when called from a click, "this" is the html element
    $("#thing").after($("<div>click me</div>").click(barf));
}

foo.prototype.bar = function() {
    alert(this);
}

person I. J. Kennedy    schedule 02.04.2009    source източник
comment
Моля, обяснете "this" is the foo instance. Следният jsfiddle(jsfiddle.net/yY6fp/1) демонстрира, че this в this.bar() се оценява на window (глобален) обект.   -  person Kevin Meredith    schedule 02.01.2014


Отговори (7)


Добре дошли в света на javascript! :Д

Вие се залутахте в царството на обхвата и затварянето на javascript.

За кратък отговор:

this.bar()

се изпълнява под обхвата на foo, (тъй като this се отнася за foo)

var barf = this.bar;
barf();

се изпълнява под глобалния обхват.

this.bar основно означава:

изпълни функцията, посочена от this.bar, под обхвата на this (foo). Когато копирате this.bar в barf и стартирате barf. Javascript, разбиран като, изпълнява функцията, посочена от barf, и тъй като няма this, той просто се изпълнява в глобален обхват.

За да коригирате това, можете да промените

barf();

към нещо подобно:

barf.apply(this);

Това казва на Javascript да обвърже обхвата на this с barf, преди да го изпълни.

За jquery събития ще трябва да използвате анонимна функция или да разширите функцията за свързване в прототипа, за да поддържате обхват.

За повече информация:

person Aaron Qian    schedule 02.04.2009
comment
Самият аз не съм 100% сигурен в терминологията, но мисля, че този отговор (и свързаните с него ресурси) объркват „обхват“ с „контекст на изпълнение“. Обектът, към който сочи this, е контекстът на изпълнение и е напълно независим от обхвата (с което затварянията имат отношение). Обхватът се определя по време на създаване на функцията и определя какви променливи може да вижда функцията; контекстът на изпълнение се определя при всяко извикване на функцията и определя за какво се отнася this. Заменете 'scope' с 'execution context' навсякъде тук и само тогава ще е правилно - мисля! - person Mark Amery; 13.06.2013

Има добро обяснение за this ключова дума в JavaScript, достъпно на QuirksMode.

person Pawel Krakowiak    schedule 02.04.2009

Може да намерите това:

Контролиране на стойността на 'this' в събитие на jQuery

или това:

http://www.learningjquery.com/2007/08/what-is-this

Полезен.

person Will Dean    schedule 02.04.2009

Вземете книгата: JavaScript: добрите части.

Освен това прочетете колкото можете повече от Дъглас Крокфорд http://www.crockford.com/javascript/

person Chris Brandsma    schedule 02.04.2009

Можете да използвате Function.apply във функцията, за да зададете към какво трябва да се отнася this:

$("#thing").after($("<div>click me</div>").click(function() {
    barf.apply(document); // now this refers to the document
});
person moff    schedule 02.04.2009
comment
Освен факта, че има липсваща затворена скоба във вашия код - функцията apply незабавно изпълнява функцията barf вместо да върне указател на функция. - person Martin; 02.04.2009

Това е така, защото това винаги е екземплярът, към който е прикачена функцията. В случай на EventHandler това е класът, който е задействал събитието.

Можете да си помогнете с анонимна функция като тази:

function foo() {
  var obj = this;
  $("#thing").after($("<div>click me</div>").click(function(){obj.bar();}));
}

foo.prototype.bar = function() {
  alert(this);
}
person Martin    schedule 02.04.2009

this.bar();  // when called here, "this" is the foo instance

този коментар е грешен, когато foo се използва като нормална функция, а не като конструктор. тук:

foo();//this stands for window
person Boki    schedule 01.02.2014