从同一原型和上下文中的另一个函数调用函数

Calling a function from another function within the same prototype and context of this

本文关键字:另一个 函数调用 函数 上下文 原型      更新时间:2023-09-26

为了遵守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,而是为了更好地理解JavaScript。

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

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

并称之为:

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

然而,在这样做的过程中,我失去了原始代码中闭包所提供的exe()的私有可见性。如果可能的话,我想保持得体。

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

如果这似乎是我努力实现的目标的一个糟糕的实现,我非常乐意考虑其他选择。

提前谢谢。

不可以,因为在定义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 $;
}());