保留它并保留jQuery上下文

时间:2013-11-07 23:59:31

标签: javascript jquery scope

我正在使用bind()在我的jQuery函数中保存this(我的类的一个实例):

if (!Function.prototype.bind) { 
    Function.prototype.bind = function(){ 
    var fn = this, args = Array.prototype.slice.call(arguments),
        object = args.shift(); 
    return function(){ 
        return fn.apply(object, 
             args.concat(Array.prototype.slice.call(arguments))); 
        }; 
    };
}

问题是,如果我有一个点击事件,例如我无法再使用$(this)访问该元素,我就无法使用。

e.g:

View.prototype.sayHelloBind = function(){
    this.$el.find('#bind').on('click', (function(){

        // This no longer works
        $(this).css('color', 'red');

        alert(this.message);
    }).bind(this));
}

正如您将在JSFiddle中看到的,我知道使用e.data,实际上,我想使用bind()的原因,所以我可以摆脱这种语法。

我的问题是,有没有办法使用bind()来保存this以及是否可以访问当前的jQuery对象?

Relevant JSFiddle

3 个答案:

答案 0 :(得分:1)

1)使用(您的)原始bind()

View.prototype.sayHelloBind = function(){
    var el = this.$el.find('#bind');
    el.on('click', (function(elem){
        $(elem).css('border', '1px solid red')
        alert(this.message);
    }).bind(this, el));
}

下行:上下文中没有event


2)您可以创建自己的bind()变体:

//if (!Function.prototype.bind_elem) {
  Function.prototype.bind_elem = function(){ 
    var fn = this, args = Array.prototype.slice.call(arguments);
    var that = args.shift(); // view
    var obj = args.shift(); // DOM object
    return function(event){ 
        var argggs = [event, obj].concat(args);
        return fn.apply(that, argggs); 
    }; 
  };
//}


var View = function(element, msg){
    this.$el = $(element);    
    this.message = msg;
}

View.prototype.sayHelloBind = function(){
    var el = this.$el.find('#bind');
    el.on('click', (function(event, elem){
        event.preventDefault();
        $(elem).css('border', '1px solid red')
        alert(this.message);
    }).bind_elem(this, el));
}

$(function(){
    var view = new View('#test', 'Hello World!');
    view.sayHelloBind();
});

一个完整的JSFiddle:http://jsfiddle.net/cek125i/24AmT/

我在上下文中添加了event,因为它通常很有用。

缺点是我们必须两次引用el

el.on('click', (func...).bind_elem(this, el));

我没有看到解决方法......


3)KISS原则?

如果用例不是特别复杂,可以使用更简单的东西:

View.prototype.sayHelloBind = function(){
    var el = this.$el.find('#bind');
    var that = this;
    el.on('click', function(event){
        event.preventDefault();
        $(this).css('border', '1px solid red')
        alert(that.message);
    });
}

答案 1 :(得分:0)

在这种情况下,您可以使用event.currentTarget来引用当前元素

View.prototype.sayHelloBind = function(){
    this.$el.find('#bind').on('click', (function(event){

        // This no longer works
        $(event.currentTarget).css('color', 'red');

        alert(this.message);
    }).bind(this));
}

演示:Fiddle

jQuery不是使用.bind(),而是提供名为$.proxy()

的跨平台实现
View.prototype.sayHelloBind = function(){
    this.$el.find('#bind').on('click', $.proxy(function(event){

        // This no longer works
        $(event.currentTarget).css('color', 'red');

        alert(this.message);
    }, this));
}

演示:Fiddle

答案 2 :(得分:0)

事件处理程序中的this必须是默认值(即单击的元素),或者它可能是您的容器对象,它不能同时存在。

由于默认语义是人们最习惯的语义,为什么不呢:

View.prototype.sayHelloBind = function() {
    var self = this;          // copy of "this" to use inside the closure
    this.$el.find('#bind').on('click', function() {

        $(this).css('color', 'red');

        alert(self.message);  // use the closed variable
    });
}

这实际上比使用.bind更有效,并且还避免了垫片。 .bind必须创建并返回一个关闭this及其参数的整个新函数,那么为什么不只是使用语言自己的功能并自己关闭this