Привязка событий jQuery OO

#javascript-objects #jquery

#javascript-объекты #jquery

Вопрос:

В принципе, у меня есть объект:

 function tomatoe(name, owner) {
    $('<div>').click(this.squish).appendTo(myElement).text('I'm a happy tomatoe called '   name);

    this.name = name;
    this.dead = false;
    this.owner = owner;
    this.squish = function() {
        console.log('Oh my Google, you killed '   this.name   '!');
        this.dead = true;
        this.owner.sad = true;
    };
}
  

Функциональность довольно проста. При создании экземпляра создайте div, прикрепите к нему обработчик щелчков и прикрепите его к чему-нибудь. При создании экземпляра передаются два параметра: имя и владелец. Владельцем является ссылка на другой объект.

С этим кодом связаны две проблемы:

  1. Ссылка this в функции squish нарушена, поскольку теперь она ссылается на элемент, на который щелкнули.
  2. Из-за цепочки при фактическом присоединении события «this» относится либо к jQuery, либо к вновь созданному элементу div (пока не уверен, к какому именно), поэтому this.squish не определен и никогда не вызывается.

Если это каким-либо образом помогает, объект owner имеет ссылку на все tomatoes.

Комментарии:

1. facepalm Я такой идиот … создание другого экземпляра самого себя описано в OO JavaScript 101

2. Все ваши ответы верны … позволю генератору случайных чисел решить, какой из них.

3. lol @Zirak обычно это первый правильный вариант, который получает торт:-p

4. Я думаю, что я зашел слишком далеко в генерации случайных чисел: jsfiddle.net/RJEyu

Ответ №1:

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

 function tomatoe(name, owner) {
    var that = this;

    that.name = name;
    that.dead = false;
    that.owner = owner;
    that.squish = function() {
        console.log('Oh my Google, you killed '   that.name   '!');
        that.dead = true;
        that.owner.sad = true;
    };

    $('<div>').click(that.squish).appendTo(myElement).text('I'm a happy tomatoe called '   name);

}
  

Комментарии:

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

2. @Zirak, ты понимаешь, что на самом деле ты не должен так выбирать ответы в stack

3. @Neal Когда за короткий промежуток времени появляется несколько ответов (например, минута или около того), все ответы считаются подлинными. OP может выбрать любой из этих ответов. Было бы по-другому, если бы этот ответ был опубликован примерно через 10 минут после другого столь же корректного ответа, но здесь это не так.

4. @Sime хорошо, я искал это в meta, и там это расплывчато

Ответ №2:

Ну, самый простой способ сделать то, что вы хотите сделать, это создать локальную переменную для хранения ссылки на объект tomatoe следующим образом:

 function tomatoe(name, owner) {
  var _this = this;
  $('<div>').click(this.squish).appendTo(myElement).text('I'm a happy tomatoe called '   name);

  this.name = name;
  this.dead = false;
  this.owner = owner;
  this.squish = function() {
    console.log('Oh my Google, you killed '   _this.name   '!');
    _this.dead = true;
    _this.owner.sad = true;
  };
}
  

Ответ №3:

попробуйте это:

 function tomatoe(name, owner) {

    //make a reference to this with self
    var self = this;

    $('<div>').click(self.squish).appendTo(myElement).text('I'm a happy tomatoe called '   name);

    this.name = name;
    this.dead = false;
    this.owner = owner;
    this.squish = function() {
        console.log('Oh my Google, you killed '   this.name   '!');
        this.dead = true;
        this.owner.sad = true;
    };
}
  

что бы я сделал, если вам нужна возможность изменения:

 var tomato = {
     name: null,
     dead: null,
     owner: null,

     init: function(name, owner){
          var self = this;
          $('<div>').click(self.squish)
                .appendTo(myElement).text('I'm a happy tomatoe called '   name);
          this.name = name;
          this.dead = false;
          this.owner = owner;
          return this;
     },

     squish: function(){
          console.log('Oh my Google, you killed '   this.name   '!');
          this.dead = true;
          this.owner.sad = true;
          return this;
     }

}

//to instantiate it:
tomato.init(name, owner);
  

Комментарии:

1. Симе, я полагаю, что это все еще относится к правильному this во вложенном fn, хотя я могу ошибаться

2.@Neal Да, ты прав. Однако строка jQuery должна отображаться под this.squish назначением. Вам вообще не нужно создавать self переменную — inside click() this по-прежнему ссылается на экземпляр.

3. @Sime, это возможно, но не то же самое в моем решении json

4. @Neal Нет, подождите, вы не правы :) . Функция используется в качестве обработчика кликов. Следовательно, this относится к элементу, на который нажимается (DIV), а не к объекту экземпляра.

5. @Neal Я имею в виду ваш первый блок кода. При выполнении строки jQuery значение self.squish не определено, поскольку ему еще не было присвоено значение.

Ответ №4:

Вы должны поместить строку jQuery после this.squish назначения! Очевидно, что оно не определено, пока вы не присвоите ему значение.

 function tomatoe(name, owner) {  

    var that = this;

    this.name = name;
    this.dead = false;
    this.owner = owner;
    this.squish = function() {
        console.log('Oh my Google, you killed '   that.name   '!');
        that.dead = true;
        that.owner.sad = true;
    };

    $('<div>').click(this.squish).appendTo(myElement)
              .text('I'm a happy tomatoe called '   name);

}