Как создать правильные замыкания в jQuery? - PullRequest
3 голосов
/ 26 августа 2009

Это пример моего кода:

var bar = function() {

  this.baz = function() {
    this.input = $('.input');
    this.input.bind("keydown keyup focus blur change", this.foo);
  }

  this.foo = function(event){
    console.log(this);
  }

}

Нажав на мой ввод, я получаю input в консоли, очевидно. Как я могу получить bar как this вместо?

Ответы [ 4 ]

5 голосов
/ 26 августа 2009

Это происходит потому, что когда вы связываете событие, функция обработчика события вызывается в контексте элемента DOM, который вызвал событие, ключевое слово this представляет элемент DOM.

Для получения "бара" следует хранить ссылку на внешнее закрытие:

var bar = function() {
  var self = this;

  this.baz = function() {
    this.input = $('.input');
    this.input.bind("keydown keyup focus blur change", this.foo);
  }

  this.foo = function(event){
    console.log(this); // the input
    console.log(self); // the bar scope
  }
};

Примечание: Если функция bar вызывается без оператора new, this будет объектом окна, а baz и foo станут глобальными переменными , будь осторожен!

Однако я думаю, что ваш код может быть упрощен:

var bar = {
  baz: function() {
    var input = $('.input');
    input.bind("keydown keyup focus blur change", this.foo);
  },

  foo: function(event){
    console.log(this); // the input
    console.log(bar); // reference to the bar object
  }
};
1 голос
/ 26 августа 2009

Это общая проблема при использовании методов экземпляра в качестве обратных вызовов в JavaScript. Я использую эту функцию, чтобы создать замыкание для вызова метода, привязанного к правильному экземпляру:

function bound_method(instance, method) {
  return function() {
    return method.apply(instance, arguments);
  };
}

Тогда вы можете использовать это как ваш обратный вызов вместо this.foo:

bound_method(this, this.foo)

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

var bar = function() {};
$.extend(bar, {
  baz: function() {
    this.input = $('.input');
    this.input.bind("keydown keyup focus blur change",
                    bound_method(this, this.foo));
  },

  foo: function(event) {
    console.log(this);
  }
});
1 голос
/ 26 августа 2009

, чтобы получить бар в вашем фу, сделайте это:

bar = function() {

var me = this;

this.baz = function() {
    this.input = $('.input');
    this.input.bind("keydown keyup focus blur change", this.foo);
}

this.foo = function(event){
    // me, would be your bar object.
    console.log(me);
}

}
0 голосов
/ 26 августа 2009

Вот, пожалуйста. Это пример того, как получить «это»

<html>
<head></head>
<script  type="text/javascript" src="jquery-1.3.2.min.js"></script>

<script>
 var  bar = function() {

this.baz = function() {
    this.input = $('.input');
    this.input.bind("keydown keyup focus blur change", this.foo);
}

this.foo = function(event){
    console.log(this);
}

}

</script>
<body>
<input class="input">
<button onclick="new bar().baz()">Click</button>
</body>
</html>

Это происходит потому, что функция baz вызывается с экземпляром bar. SO bar выполняется в контексте "new bar ()", а не в объекте window.

Если вы используете firebug (кажется, так), вы можете отслеживать ведение журнала при вводе текста в элементе управления вводом текста до и после нажатия кнопки мыши на вкладке консоли.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...