2009-08-26 2 views
3

Это пример моего кода:Как создать правильные закрытия в jQuery?

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?

ответ

5

Это происходит потому, что, когда событие bind событие, функция обработчика событий вызывается с контекстом элемента 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 
    } 
}; 

Примечание: Если функция бара вызывается без оператора 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 
    } 
}; 
+0

Я бы добавил, что вам действительно не нужна часть «var bar =». Чтобы вызвать замыкание в строке, добавьте «()» перед последней точкой с запятой. – spoulson

+2

Да, но обратите внимание также, что если закрытие выполняется автоматически, 'baz' и' foo' станут глобальными, так как 'this' будет объектом window. – CMS

+0

Спасибо, я думаю, я поеду с этим вариантом «внешнего закрытия». Но я надеялся на что-то большее, ну, элегантное, вроде a, dunno, second bind внутри input.bind(). У меня такое чувство, что я где-то видел что-то подобное. Есть ли другие варианты? – n1313

1

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

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

Здесь go.This является exmaple о том, как получить «это "

<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 выполняется в рамках" нового bar() ", а не объект окна.

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

1

Это общая проблема при использовании методов экземпляра в качестве обратных вызовов в 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); 
    } 
}); 
+0

Ваш метод bound_method() очень похож на bind(), правильно? – n1313

+0

Да, это очень похоже на Function.bind в Prototype или на новые стандарты ECMAScript.Я хотел бы добавить его в прототип Function, но мы избегаем модификации встроенных прототипов объектов. –

Смежные вопросы