MooTools在方法和内部函数中绑定/保持类范围

时间:2011-12-15 17:52:42

标签: javascript scope mootools

我正在尝试使用Mootools动态地向页面添加按钮。除addEvent函数中的addButton外,一切正常。我得到一个错误,说“对象javascript:void(0);”属性'sayHi'不是函数“。

我认为这是由于我的范围,我不知何故必须将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'));
    }
});    

4 个答案:

答案 0 :(得分:2)

问题在于,在您的点击处理程序中,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'));
    }
});    

答案 1 :(得分:2)

您遇到此问题是因为执行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'));
}

HERE 是正在运行的示例。切换到“代码”视图以查看源。

答案 2 :(得分:1)

推荐的处理方法是在很多mootools中插入更多插件如下:

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解决方案非常相似,但您不需要使用函数调用来包装您的类。

恕我直言,它使代码更清洁/可维护/摩擦!

希望这有帮助。

答案 3 :(得分:1)

Omg,绑定怎么样?做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'));
}
});  

您可以查看here