21

我将 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 之前在外部存储对函数的引用并通过该引用调用默认验证器没有区别。

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

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

4

8 回答 8

18

在调用 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);
于 2009-01-15T17:42:35.620 回答
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 构造函数是一样的。字面量要好得多。并且仅仅为此包括 JQuery,而且如果它不能正常工作(我认为它不能正常工作)并不是你能做的最聪明的事情。

于 2010-03-29T20:20:05.177 回答
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() 函数覆盖,都将保留该函数的任何未来调用。

这可以对您有利或不利,具体取决于您如何处理它。

于 2011-07-21T07:30:42.643 回答
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);
于 2009-01-15T17:58:38.800 回答
4

(这应该只是对Can I copy/clone a function in 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();ab克隆?怎么样o = Object; a = new o(); b = new o();
  • 真的需要吗?
  • 克隆在哪里停止?原型属性是否也被隔离,因此克隆对象对这些属性的更改不会影响与克隆对象无关的实例?在这种情况下,克隆必须一直沿原型链向上到达原始构造函数,它们本身需要以某种方式克隆和隔离(浏览器中的一个技巧是打开一个新窗口并用警告重新填充它opener .等仍然可以泄漏交叉效应)
于 2014-03-18T21:53:02.740 回答
2

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

Function.prototype.clone=function(){
    return eval('['+this.toString()+']')[0];
}
于 2009-02-11T22:20:31.840 回答
1

听起来没有“更好的方法”。我想您可以尝试为自己制作自定义所需的功能,例如:

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

听起来您已经尝试了其他所有方法。如果我误解了这个问题,我深表歉意。

于 2009-01-15T17:31:54.767 回答
0

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

`

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 引擎的执行速度。

于 2009-06-09T19:32:24.857 回答