バリデータプラグインで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を呼び出す前に関数への参照を外部に保存し、その参照を介してデフォルトのバリデーターを呼び出すことには違いはありません。
私が本当にする必要があるのは、デフォルトで必要なバリデーター関数を参照ではなく値でコピーできるようにすることです。しかし、かなりの検索の後、私はそれを行う方法を理解することができません。出来ますか?
それが不可能な場合は、元の関数のソースをコピーできます。しかし、それはメンテナンスの問題を引き起こし、「より良い方法」がない限り、私はむしろそれをしたくありません。
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);
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()を使用することは完全に愚かで、長すぎて、関数コンストラクターは同じようなものです。 Literralsははるかに優れています。そして、そのためだけにJQueryを含めると、さらに、それが適切に機能しない場合(そして、私はそれが機能するとは思わない)、あなたができる最も明るいことではありません。
これが更新された答えです
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」引数uが提供されました(上記の空白{})。 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()+')' );
}
効率についての考え:
クローン作成について:この質問は非常に修辞的である可能性があります
a = new Object(); b = new Object();
がa
およびb
クローンの場合? o = Object; a = new o(); b = new o();
はどうですかopener .
などができる警告を再入力することです。それでもクロスエフェクトをリークします)関数のクローンを作成したい場合は、これを試してください:
Function.prototype.clone=function(){
return eval('['+this.toString()+']')[0];
}
「より良い方法」はないようです。私はあなたがあなた自身のためにカスタム必須関数を作ってみることができると思います例えば:
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'};
`
いくつかのテストを実行して、これが優れたJSエンジンでの実行を遅くしないことを確認します。