我可以在JavaScript中复制/克隆一个函数吗?

时间:2009-01-15 17:22:10

标签: javascript jquery validation jquery-validate

我正在使用带有验证器插件的jQuery。我想用自己的一个替换“必需的”验证器。这很简单:

jQuery.validator.addMethod("required", function(value, element, param) {
    return myRequired(value, element, param);
}, jQuery.validator.messages.required);

到目前为止,这么好。这很好用。但我真正想要做的是在某些情况下调用我的函数,以及其余的默认验证器。不幸的是,这结果是递归的:

jQuery.validator.addMethod("required", function(value, element, param) {
    // handle comboboxes with empty guids
    if (someTest(element)) {
        return myRequired(value, element, param);
    }
    return jQuery.validator.methods.required(value, element, param);
}, jQuery.validator.messages.required);

我查看了验证器的源代码,并且“required”的默认实现在jQuery.validator.messages.required中定义为匿名方法。所以没有其他(非匿名)引用我可以使用的函数。

在调用addMethod之前在外部存储对函数的引用,并通过该引用调用默认验证器没有任何区别。

我真正需要做的是能够按值而不是通过引用复制默认的必需验证器函数。但经过相当多的搜索,我无法弄清楚如何做到这一点。有可能吗?

如果不可能,那么我可以复制原始功能的来源。但这会产生维护问题,除非没有“更好的方法”,否则我宁愿不这样做。

8 个答案:

答案 0 :(得分:17)

  

存储对该功能的引用   在调用addMethod之前从外部   并通过调用默认验证器   这个参考没有区别。

这正是应该起作用的

jQuery.validator.methods.oldRequired = jQuery.validator.methods.required;

jQuery.validator.addMethod("required", function(value, element, param) {
    // handle comboboxes with empty guids
    if (someTest(element)) {
        return myRequired(value, element, param);
    }
    return jQuery.validator.methods.oldRequired(value, element, param);
}, jQuery.validator.messages.required);

这也应该有效:(并解决了this的问题)

var oldRequired = jQuery.validator.methods.required;
jQuery.validator.addMethod("required", function(value, element, param) {
    // handle comboboxes with empty guids
    if (someTest(element)) {
        return myRequired(value, element, param);
    }
    return oldRequired.call(this, value, element, param);
    // return jQuery.oldRequired.apply(this, arguments);
}, jQuery.validator.messages.required);

答案 1 :(得分:9)

Function.prototype.clone = function() {
    var fct = this;
    var clone = function() {
        return fct.apply(this, arguments);
    };
    clone.prototype = fct.prototype;
    for (property in fct) {
        if (fct.hasOwnProperty(property) && property !== 'prototype') {
            clone[property] = fct[property];
        }
    }
    return clone;
};

唯一不好的是原型没有被克隆,所以你无法真正改变它...... 我正在研究克隆任何类型的对象的方法,我只剩下RegExp了。 所以我明天可能会编辑并放入整个代码(如果你只将它用于函数和对象,它就会很长并且没有优化。

并且评论其他答案,使用eval()完全是愚蠢的,并且太长,而且Function构造函数有点相同。 Literrals要好得多。 并且包括JQuery就是为了这个,而且如果它不能正常工作(我认为它没有)并不是你能做的最聪明的事情。

答案 2 :(得分:5)

这是更新的答案

var newFunc = oldFunc.bind({}); //clones the function with '{}' acting as it's new 'this' parameter

然而.bind是JavaScript的一个新功能,但有一个Mdn

的解决方法

https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind

此外,它不会克隆功能附加属性。

注意:正如@gsnedder所指出的那样:绑定语句,你提供的“this”参数(上面的空白{})。无论是否通过apply()/ call()函数进行覆盖,都将继续执行该函数的任何调用。

根据您的处理方式,这可以用于您的优势或劣势。

答案 3 :(得分:4)

我认为你只是缺少一些范围。试试这个:

jQuery.validator.methods._required = jQuery.validator.methods.required;
jQuery.validator.addMethod("required", function(value, element, param) {
    // handle comboboxes with empty guids
    if (someTest(element)) {
        return myRequired(value, element, param);
    }
    return jQuery.validator.methods._required.call(this, value, element, param);
}, jQuery.validator.messages.required);

答案 4 :(得分:3)

(这应仅是对Can I copy/clone a function in JavaScript?的评论...不幸的是,代表< 50只能发布)

Function.prototype.clone=function(){
    return eval( '('+this.toString()+')' );
}

足够,甚至

Object.prototype.clone=function(){
    return eval( '('+this.toString()+')' );
}

关于效率的想法:

  • 人类效率远比浪费人类更重要 优化或改善机器“生命”的资源
  • 计算机和自动化系统应该减少人力 不要增加它
  • 计算开销必须严重影响结果的适口性 许多人为了人类的消费而进行投资 优化代码的努力往往变得更加模糊,晦涩难懂 如此深奥,以至于它无法被一个稳定的人所理解 程序员在数小时试图“理解”逻辑之后

关于克隆:这个问题可能非常夸张

  • “克隆”javascript对象是什么意思?特别是在递归函数理论的背景下
    • 使克隆合理化的一个共同主题是,它可以隔离并“保护”原创者免受其变化的影响
    • 如果a = new Object(); b = new Object();ab克隆? o = Object; a = new o(); b = new o();
    • 怎么样?
  • 真的需要吗?
  • 克隆停在哪里?是典型的属性 孤立也是如此克隆对象的这些变化不会影响 与克隆对象无关的实例?在这种情况下 克隆必须一直沿着原型链到达 原始的构造函数本身需要以某种方式 克隆和隔离(在浏览器中的一个技巧是打开一个新窗口,并重新填充它,opener .等仍可能泄漏交叉影响的警告

答案 5 :(得分:2)

如果你想克隆一个函数,试试这个:

Function.prototype.clone=function(){
    return eval('['+this.toString()+']')[0];
}

答案 6 :(得分:1)

听起来没有'更好的方法'。我想你可以尝试为自己制作一个自定义的功能,例如:

jQuery.validator.addMethod("customRequired", function(value, element, param) {
  return myRequired(value, element, param);
}, jQuery.validator.messages.required);

听起来你已经尝试了其他一切。如果我误解了这个问题,请道歉。

答案 7 :(得分:0)

回答上一篇文章,当我需要共享一个构造函数,同时保持不同的原型时,我在一个新函数中使用了一个包装器:

`

init_from_arg_obj = function () {
    return new Function('init', 'for (var i in init) this[i] = init[i];');
};

constructor_A = init_from_arg_obj();
constructor_A.prototype = {a: 'A'};

constructor_B = init_from_arg_obj();
constructor_B.prototype = {b: 'B'};

`

我运行了几个测试来验证这不会减慢良好JS引擎上的执行速度。