Перезаписана проблема «этой» переменной или как вызвать функцию-член? - PullRequest
1 голос
/ 10 апреля 2009

У меня есть этот класс, где я использую комбинацию jQuery и Prototype :

var MyClass = Class.create({
    initElements: function(sumEl) {
       this.sumEl = sumEl;
       sumEl.keyup(this.updateSumHandler);
    },

    updateSumHandler: function(event) {
       // Throws error here: "this.updateSum is not a function"
       this.updateSum();
    },

    updateSum: function() {
       // does something here
    }
});

Как мне все-таки позвонить this.updateSum()?

Ответы [ 4 ]

5 голосов
/ 10 апреля 2009

Вам нужно использовать замыкания.

 initElements: function(sumEl) {
        this.sumEl = sumEl;
        var ref = this;
        sumEl.keyup( function(){ref.updateSumHandler();});
 },
4 голосов
/ 10 апреля 2009

Полностью непроверенное предложение:

sumEl.keyup(this.updateSumHandler.bind(this));

.bind() возвращает новую функцию, в которой первый параметр bind закрыт для вас как контекст this функции. Он также может закрывать параметры, ознакомьтесь с документацией .

Для меня Function.bind() - единственная лучшая функция, написанная на JavaScript:)

1 голос
/ 10 апреля 2009

Обработчики DOMEvent традиционно вызываются с элементами, в которых они зарегистрированы как context / "this". Это то, что делает jQuery тоже.

Самый простой вариант для вас - использовать возможность jQuery для обработки данных о событиях

var MyClass = Class.create({
 initElements: function(sumEl) {
        this.sumEl = sumEl;
        sumEl.bind("keyup", this, this.updateSumHandler);
 },

 updateSumHandler: function(event) {
    // event.data is the initial this

    // call updateSum with correct context
    event.data.updateSum.call(event.data);
 },

 updateSum: function() {
        // does something here
 }
});

Другая возможность - использовать замыкания для определения updateHandler внутри конструктора

var MyClass = Class.create({
 initElements: function(sumEl) {
        this.sumEl = sumEl;

        // save this as that so we can access it from the anonymous function
        var that = this;
        sumEl.keyup(function()
        {
           that.updateSum();
        });
 },

 updateSum: function() {
        // does something here
 }
});

Это рабочий пример того, что пытался сделать один из других ответов. Это работает, потому что анонимная функция всегда может получить доступ к переменным в окружающей функции, но она работает только в том случае, если функция действительно определена в функции, в которой «то» является локальной переменной.

0 голосов
/ 10 апреля 2009

Это знаменитая идиома Javascript, которую нужно использовать в функции initElements:

var that = this;

Позже в вашем обработчике просто обратитесь к that вместо this:

var MyClass = Class.create({
    initElements: function(sumEl) {
        this.sumEl = sumEl;
        var that = this;
        sumEl.keyup(this.updateSumHandler);
    },
    updateSumHandler: function(event) {
        that.updateSum();
    },
    updateSum: function() {
        // does something here
    }
});

Это было подробно описано в докладе Стюарта Лэнгриджа о Javascript замыканиях на конференции Fronteers 2008.

...