Объект JS this.method () повреждается с помощью jQuery

Не ожидайте, что JQuery будет работать на Blackberry вообще. Браузер по умолчанию очень ограничен с точки зрения JavaScript и рендеринга страниц.

Хотя опера на Blackberry может быть другой историей ...

13
задан Peter Boughton 9 October 2009 в 16:39
поделиться

4 ответа

Идентификация этого является распространенной проблемой в javascript. Он также сломается, если вы попытаетесь создать ярлык для doSomething :

var do = Bob.doSomething;
do(); // this is no longer pointing to Bob!

Хорошая практика - не полагаться на идентификатор this . Вы можете сделать это разными способами, но самый простой - явно указать Bob вместо this внутри doSomething . Другой - использовать функцию-конструктор (но тогда вы теряете классный синтаксис объектного литерала):

var createBob = function() {
    var that = {};

    that.Stuff = '';
    that.init = function() {
        that.Stuff = arguments[0];
    };

   that.doSomething = function() {
       console.log( that.Stuff );
   };

   return that;   
}

var bob = createBob();
5
ответ дан 1 December 2019 в 19:15
поделиться

Измените

$('#MyButton').click( Bob.doSomething );

на

$('#MyButton').click( function() { Bob.doSomething() } );

Вы также можете добавить к своему объекту Bob частное поле var that = this и использовать его везде в членах вместо это , если вы действительно хотите избежать анонимной функции.

например,

var Bob = new function() {
    // Private Fields
    var that = this;

    // Public Members   
    this.Stuff = '';

    this.init = function() {
                that.Stuff = arguments[0];
        }

    this.doSomething = function() {
                console.log( that.Stuff );
        }
}
8
ответ дан 1 December 2019 в 19:15
поделиться

Это не ошибка jQuery, это неотъемлемая часть того, как JavaScript обрабатывает объекты.

В отличие от большинства других объектно-ориентированных языков, 'this' не привязано на уровне каждого метода в JavaScript; вместо этого он определяется исключительно способом вызова функции:

Bob= {
    toString: function() { return 'Bob!'; },

    foo: function() { alert(this); }
};
Brian= {
    toString: function() { return 'Brian!'; },
};

Bob.foo(); // Bob!
Bob['foo'](); // Bob!

Brian.foo= Bob.foo;
Brian.foo(); // Brian! NOT Bob

var fn= Bob.foo;
fn(); // window NOT Bob

То, что вы делаете в случае:

$j('#MyButton').click( Bob.doSomething );

, похоже на последний пример с fn : вы вызываете функцию doSomething от Боба и передает его установщику обработчика событий jQuery как чистую функцию: он больше не имеет связи с Бобом или любым другим объектом, поэтому вместо этого JavaScript передает глобальный объект window . (Это одна из худших особенностей дизайна JavaScript, так как вы можете не сразу заметить, что window не Bob , и начать доступ к его свойствам, вызывая странные и сбивающие с толку взаимодействия и ошибки.)

Чтобы запомнить Боба, вы обычно создаете функцию, как в ответе Никита, чтобы сохранить копию «Боб» в замыкании, чтобы ее можно было запомнить в время обратного вызова и используется для вызова реального метода. Однако теперь есть стандартизированный способ сделать это в ECMAScript Fifth Edition:

$j('#MyButton').click( Bob.doSomething.bind(Bob) );

(Вы также можете добавить дополнительные аргументы в вызов bind , чтобы вызвать doSomething обратно с ними, то есть удобно.)

Для браузеров, которые еще не поддерживают метод bind () пятой редакции изначально (а на данный момент их большинство), вы можете взломать свою собственную реализацию bind ( библиотека прототипов тоже делает то же самое), что-то вроде:

if (!Object.bind) {
    Function.prototype.bind= function(owner) {
        var that= this;
        var args= Array.prototype.slice.call(arguments, 1);
        return function() {
            return that.apply(owner,
                args.length===0? arguments : arguments.length===0? args :
                args.concat(Array.prototype.slice.call(arguments, 0))
            );
        };
    };
}
24
ответ дан 1 December 2019 в 19:15
поделиться

Вы всегда можете попробовать сделать что-то вроде этого:

$j('#MyButton').click(function(event) {
  Bob.doSomething(event, this);
});

Теперь doSomething по-прежнему будет иметь Боб в качестве this , и с использованием аргументов функции он будет иметь объект event и элемент, по которому он был запущен.

0
ответ дан 1 December 2019 в 19:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: