jQuery对象的函数重载

5

我正在尝试向具有与另一个方法相同名称(但参数集不同)的jQuery对象添加一个方法。

目前为止,我已经完成了以下工作:

jQuery.fn.insertBefore = function(elem, duration)
{
    this.css("display", "none");
    this.insertBefore(elem);
    this.toggle(duration);
}

然而,这段代码(特别是this.insertBefore(where);行)调用了同一个函数,而不是所需的jQuery insertBefore()函数。我需要怎么做才能将此函数添加到jQuery对象中,并使其重载(而不是覆盖)现有函数? 编辑:解决方案
(function ($)
{
    var oldInsertBefore = $.fn.insertBefore;
    jQuery.fn.insertBefore = function(elem, duration)
    {
        if (duration === undefined)
        {
            oldInsertBefore.call(this, elem);
            return;
        }

        this.css("display", "none");
        this.insertBefore(elem);
        this.toggle(duration);
    }
})(jQuery);
4个回答

6
在覆盖函数之前,您需要备份原始函数。可以像这样进行备份:
(function($){
    var oldInsertBefore = $.fn.insertBefore;
    jQuery.fn.insertBefore = function(elem, duration)
    {
        oldInsertBefore.apply(this, arguments);
        this.css("display", "none");
        this.insertBefore(elem);
        this.toggle(duration);
    }
})(jQuery);

这会每次调用新的 insertBefore 函数的其余部分吗?还是它可以在何时调用旧函数与新函数之间做出区分? - Patrick Perini
执行此代码后,原始的 insertBefore 将被替换。在您的替换版本中,您可以决定何时调用原始版本。 - Sergio Tulentsev
1
我会应用类似于 if( typeof duration == 'undefined' ) { oldInsertBefore.apply(this, arguments); return; } 的东西。 - Matmarbon

4
您可以使用 $.sub()
(function($){
    var sub$ = $.sub();

    sub$.fn.insertBefore = function(where, duration) {
       this.css("display", "none");
       this.insertBefore(where);
       this.toggle(duration);
    }

    /* you can use this plugin in this scope or you could also
       return sub$ and call the plugin outside */
})(jQuery);

$.sub()的说明:

创建一个新的 jQuery 副本,其属性和方法可以修改而不影响原始的 jQuery 对象。

来源:http://api.jquery.com/jQuery.sub/


0
寻找解决某些问题的方法,我来到了这里,但发现我从未需要任何形式的重载。在自己的JS类中使用jQuery,我有以下代码:
class myClass
{
    appendMessage(elementObj, message) {
        ...
    }

    appendOrReplaceMessage(elementObj, message) {
        let that = this;
        let elObj = elementObj;
        let msg = message;
        if (elementObj.parent().find('span.error').length) {
            this.disableNextButton(elementObj);
            elementObj.parent().find('span.error').each(function(index, element) {
                $(element).hide({
                    duration: 300,
                    complete: (function() {
                        $(element).remove();
                        that.appendMessage(elObj, msg);
                    })
                })
            });
        } else {
            this.appendMessage(elementObj, message);
        }
    }
}


这段代码的挑战在于,在each函数内,变量this的含义与外部不同。因此,我不能使用外部类的上下文来调用this.appendMessage()方法。在appendOrReplaceMessage()方法中添加声明后,我可以将外部对象用作that,并且已声明的变量也都可在each函数中使用。
这并没有回答问题,但或许显示了绕过问题的一种方法。

与问题相关的,需要提到jQuery函数before()允许使用函数作为回调,而这个选项在jquery函数insertBefore()中不可用。使用正确的函数是避免过于复杂的代码显然是必要的。 因此,问题的代码可以像这样使用,可能需要进行一些调整才能使其按照预期工作:

before((function(index){
        this.css("display", "none");
        this.insertBefore(elem);
        this.toggle(duration);
}));

我的第一个代码块旁边的解释可能有助于获取before()函数内变量elemduration的值。

jQuery API - before()
jQuery API - insertBefore()


0
从技术角度来看,JavaScript不允许您定义具有相同名称但不同参数的单独函数。您只能拥有一个具有相同名称的函数,尽管它不关心通过多少参数传递。上面发布的所有解决方案都利用了这一点,但最终只是将原始函数重命名并调用它。除非有非常好的理由,否则建议为自定义方法提供不同的名称,以避免与现有函数发生冲突。想象一下其他人试图添加到您的代码库,却没有意识到标准jQuery方法被覆盖。
您自己的方法可以接受任意数量的参数,可以通过arguments对象访问这些参数。您可以执行诸如arguments.length之类的操作,或者仅检查您的参数是否存在,以确定传递了多少个/哪些参数(请参见:https://developer.mozilla.org/en/JavaScript/Reference/Functions_and_function_scope/arguments)。
在jQuery中,更标准的做法是在创建自定义插件时只传递选项对象,如here所述。

你为什么要这样做呢?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接