MooTools在方法和内部函数中绑定/保持类作用域

MooTools binding/keeping class scope in methods and inner functions

本文关键字:作用域 绑定 方法 内部函数 MooTools      更新时间:2023-09-26

我试图使用Mootools动态添加一个按钮到页面。一切都很好,除了addButton函数中的addEvent。我得到一个错误说"属性'sayHi'的对象javascript:void(0);不是一个函数".

我认为这是由于我的作用域,我必须以某种方式将addButton函数绑定回全局"this"?有人能解释一下我哪里做错了吗?谢谢!

var myClass = new Class({
    initialize: function(){
        this.sayHi();
    },
    sayHi: function(){
        alert('Hello World!');
    },
    addButton: function(){
        this.hiButton = new Element('a', {
            id: 'sayhi',
            html: 'Hi!',
            href: 'javascript:void(0);',
            events: {
                click: function(){
                    this.sayHi();
                }
            }
        }).inject($('myDiv'));
    }
});    

问题在于,在您的点击处理程序中,this值不再是原始对象,而是被点击的按钮。

可能有特定于mootools的方法来解决这个问题,但是将这个对象创建包装在函数中将是解决这个问题的简单、本地方法:

function getMyClass(){
   var self = new Class({
       initialize: function(){
           this.sayHi();
       },
       sayHi: function(){
           alert('Hello World!');
       },
       addButton: function(){
           this.hiButton = new Element('a', {
               id: 'sayhi',
               html: 'Hi!',
               href: 'javascript:void(0);',
               events: {
                   click: function(){
                       self.sayHi();
                   }
               }
          }).inject($('myDiv'));
       }
   });
   return self;
}    

var myClass = getMyClass();

编辑

虽然上面是JavaScript中相当标准的习惯用法,但我被告知它不适用于MooTools。如果是这样的话,我会这样做(正如另一个答案已经提到的):

var myClass = new Class({
    initialize: function(){
        this.sayHi();
    },
    sayHi: function(){
        alert('Hello World!');
    },
    addButton: function(){
        var self;
        this.hiButton = new Element('a', {
            id: 'sayhi',
            html: 'Hi!',
            href: 'javascript:void(0);',
            events: {
                click: function(){
                    self.sayHi();
                }
            }
        }).inject($('myDiv'));
    }
});    

你得到这个问题,因为当click处理程序执行this是代表anchor元素对象,而不是你的myClass

addButton更改为:

addButton: function(){
    var that = this;
    this.hiButton = new Element('a', {
        id: 'sayhi',
        html: 'Hi!',
        href: 'javascript:void(0);',
        events: {
            click: function(){
                that.sayHi();
            }
        }
    }).inject($('myDiv'));
}

这里是运行示例。切换到代码视图查看源代码

处理此问题的建议方法如下:

var myClass = new Class({
    initialize: function(){
        this.sayHi();
    },
    sayHi: function(){
        alert('Hello World!');
    },
    addButton: function(){
        var self = this;
        this.hiButton = new Element('a', {
            id: 'sayhi',
            html: 'Hi!',
            href: 'javascript:void(0);',
            events: {
                click: function(){
                    self.sayHi();
                }
            }
        }).inject($('myDiv'));
    }
});

你可以看到它与Adam Rackis的解决方案非常相似,但是你不需要用函数调用包装你的类。

IMHO它使代码更干净/可维护/mooish!

天哪,绑定呢?做var self = this;是错误的。你可以这样做:

var myClass = new Class({
initialize: function(){
    this.sayHi();
},
sayHi: function(){
    alert('Hello World!');
},
addButton: function(){
    this.hiButton = new Element('a', {
        id: 'sayhi',
        html: 'Hi!',
        href: '#',
        events: {
            click: function(){
                this.sayHi();
                // this will stop event propagation
                return false;
            }.bind(this)
        }
    }).inject($('myDiv'));
}
});  

可以在这里勾选