0

为了保持 DRY 原则,我决定修改函数的原型以减少 function.call() 调用的数量。

以下是我目前拥有的内容的片段,并进一步说明了我正在尝试做的事情。

com.domain.$ = function(s){
     if(!this){return new com.domain.$(s);}

    this.selector = s;
    this.elements = document.querySelectorAll(s);
}

com.domain.$.prototype = (function(){
    function exe(f){
        var e = this.elements,
            el = e.length;
        for(var i=0; i<el; i++){
            f(e[i]);
        }
    }

    function addClass(c){exe.call(this,function(el){el.classList.add(c);});}
    function removeClass(c){exe.call(this,function(el){el.classList.remove(c);});}
    function toggleClass(c){exe.call(this,function(el){el.classList.toggle(c);});}

    return {
        addClass:addClass,
        removeClass:removeClass,
        toggleClass:toggleClass
    }
}());

我意识到这看起来很像我试图模仿 jQuery 的功能。虽然是有意的,但这并不意味着作为替代品,而是为了更好地理解 JavaScript。

也就是说,我想做的是消除调用exe()via的需要exe.call(this[, fnc]);,以便使上下文this成为我想要的。我相信我可以通过函数绑定 ( .bind()) 来做到这一点,尽管可能不是我想要的方式。我知道可以改为执行以下操作:

com.domain.$.prototype.exe = function(){}

并称之为:

function addClass(c){this.exe(function(){});}

但是,这样做时,我失去了exe()原始代码中闭包提供的私有可见性。如果可能的话,我想保持原样。

那么,我的问题是,是否有可能exe()在我的原始代码中进行绑定,从而减少对 的冗余使用,为withinexe.call(this拥有正确的上下文,并在闭包中保持私有可见性?thisexe()

如果这似乎是我想要完成的一个糟糕的实现,我很乐意考虑其他选择。

先感谢您。

4

1 回答 1

1

不,你不能,因为在你定义的那一刻exe(),你想要调用的实例exe()还不存在。

事实上,如果您要多次调用com.domain.$,您将使用不同的实例,因此绑定到特定exe()实例是没有意义的。exe()

如果你想这样做,你必须在构造函数中定义所有这些方法,你会失去原型的所有优点:

(function() {
    function exe(f){
        // ...
    }

    com.domain.$ = function(s){
        // ...

        var exe_ = exe.bind(this);
        this.addClass = function(c) {
             exe_(function(el){el.classList.add(c);});
        };
        // ...
    };
}());

我建议,如果您不想使用.call,只需进行修改exe(),以便它接受一个元素数组作为参数并this.elements从原型函数传递给它。我不明白为什么exe()需要使用this。它只是一个将数组的每个元素传递给给定函数的助手,并且通过使其更通用,它更容易重用。
例如:

var com.domain.$ = (function(o) {
    function exe(arr, f){
        var el = e.length;
        for(var i=0; i<el; i++){
            f(arr[i]);
        }
    }

    var $ = function(s){
         // ...
    }

    $.prototype.addClass = function(c){
        exe(this.elements, function(el){
            el.classList.add(c);
        });
    };
    // ... 

    return $;
}());
于 2012-08-24T17:30:00.293 回答