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

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

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

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

 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); 

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

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

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

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

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

这正是应该工作的

 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); 
 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只是为了它,而且如果它不能正常工作(我认为它没有)并不是你能做的最聪明的事情。

这是一个更新的答案

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

然而.bind是JavaScript的一个新function,但有一个Mdn的解决方法

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

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

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

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

我想你只是缺少一点范围。 试试这个:

 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); 

(这应该只是一个注释我可以在JavaScript中复制/克隆一个函数吗? …不幸的是,rep <50只能发布)

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

足够,甚至

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

关于效率的想法:

  • 人力效率远远超过浪费人力资源来优化或改善机器的“生命”
  • 计算机和自动化系统应该减少人力,而不是增加它
  • 计算开销必然会严重影响结果对人类消费的适应性,这是许多人为了优化代码而付出的努力,这些代码往往变得更加模糊,晦涩和深奥,以至于经过数小时的努力后,稳定的程序员无法再理解它“理解”逻辑

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

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

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

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

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

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

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

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

`

 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'}; 

`

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