Javascript 从原型类改进此代码段

Javascript 从原型类改进此代码段,javascript,class,refactoring,prototypejs,Javascript,Class,Refactoring,Prototypejs,这是我正在编写的原型类的一个片段。对我来说,范围界定工作区有点麻烦,是否可以改进或以不同的方式完成 var myClass = Class.create({ initialize: function() { $('formid').getElements().each(function(el){ $(el).observe("blur", function(){ this.validateEl(el);

这是我正在编写的原型类的一个片段。对我来说,范围界定工作区有点麻烦,是否可以改进或以不同的方式完成

var myClass = Class.create({
    initialize: function() {
        $('formid').getElements().each(function(el){
            $(el).observe("blur", function(){
                this.validateEl(el);
            }.bind(this,el));
        },this);
     },
    validateEl: function(el){
      // validate $(el) in here...
    }
});
此外,在我看来,我可以为活动观察员做类似的事情:

$('formid').getElements().invoke("observe","blur" ...

但不确定如何传入元素引用?

我看不出您的代码有什么问题:)

关于观察员,您可以这样做:

$('formid').getElements().invoke("observe","blur", function(e) {
    this.validateEl(e.element());
}.bind(this));

您确实可以将其简化一点:

var myClass = Class.create({
    initialize: function() {
        var self = this;

        // To demo that we keep the instance reference, set a
        // property on the instance
        this.message = "Hi there";

        $('formid').getElements().invoke("observe", "blur", blurHandler);

        function blurHandler() {
            // `self` references our instance
            // `this` references the element we're observing
            self.validateEl(this);
        }
    },
    validateEl: function(el){

        // validate $(el) in here...

        // note that because of the way we called it, within this function,
        // `this` references the instance, so for instance:
        this.foo(); // alerts "Hi there!"
    },
    foo: function() {
        alert(this.message);
    }
});
它使用
invoke
(如您所建议的)和处理程序的命名函数(不必命名,但我发现让函数具有名称非常有用)。处理程序是一个闭包。在
initialize
函数中,我使用一个变量指向
this
,因为该变量随后将可用于闭包。(我称之为
self
,因为这是为此而使用
this
别名的标准做法。)处理程序利用Prototype的本机功能,在事件处理程序中设置
this
,以观察到的元素。当我们通过闭包的
self
引用调用
validateEl
时,我们按照常规将其作为成员函数调用,因此在
validateEl
中,
引用实例


说到命名函数,您的
initialize
validateEl
函数都是匿名的,这意味着在调用堆栈和调试器中,您只会看到“(?”,而不是一个好用的名称。我总是建议使用实际命名的函数

我认为,如果创建一个
registerBlur
方法,它看起来会稍微不那么冗长:

var myClass = Class.create({
    initialize: function() {
        $('formid').getElements().each(this.registerBlur, this);
    },
    registerBlur: function(el) {
        Event.observe(el, 'blur', this.validateEl.bind(this, el));
    },
    validateEl: function(el){
      // validate $(el) in here...
    }
});

但是我同意Rui Carneiro的观点,我也不认为您的代码有任何错误。

感谢您提供有关命名函数的信息,这非常值得考虑。但在您的示例中,如果我需要从validateEl函数中的类内调用另一个函数,我可能会遇到范围问题,除非我首先在class@seengee:不,您可以使用标准的
this.foo
表示法来完成。在
validateEl
中,
这个
将引用该实例,这是因为我们调用它的方式。当您通过属性进行函数调用时,就像使用
self.validateEl(…)
一样,它意味着“调用
validateEl
,并使调用中的
this
等于
self
”。更多信息:@TJ-wow,谢谢你提供的所有细节。一些非常好的信息there@TJ-我可能会使用另一种方法,但我从你的回答中学到了很多,因此指向你:)虽然它有效,但使用
event.element
这里的工作比需要的多得多。此外,尽管使用模糊(因为它不会冒泡)是安全的,但您不希望使用单击的模糊或任何冒泡的事件,因为元素将返回单击的最底部元素(可能是span、em、a,等等),不是你观察到的元素。有时这是你想要的,有时不是。@TJ-这是一个很好的冒泡呼吁-当你说它比所需的工作量大时,你的意思是纯粹与你的闭包示例相比吗?@seengee:closure或binding。但除非它经常发生,否则不管怎样都没什么关系。只是
event.element
做了一些额外的函数调用,如果可以直接调用的话,这些调用是不需要的,但是我们讨论的是几个调用,而不是一个或一个调用,这与事件周围发生的一切相比可能并不重要。:-)