Могу ли я копировать/клонировать функцию в JavaScript?
Я использую 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);
Я посмотрел исходный код для валидаторов, а реализация по умолчанию "требуется" определяется как анонимный метод в jQuery.validator.messages.required. Таким образом, нет другой (не анонимной) ссылки на функцию, которую я могу использовать.
Сохранение ссылки на функцию извне перед вызовом addMethod и вызовом валидатора по умолчанию через эту ссылку не имеет значения.
Мне действительно нужно сделать, чтобы иметь возможность копировать требуемую по умолчанию функцию валидатора по значению, а не по ссылке. Но после довольно многого поиска я не могу понять, как это сделать. Возможно ли это?
Если это невозможно, я могу скопировать источник исходной функции. Но это создает проблему обслуживания, и я бы предпочел не делать этого, если нет "лучшего способа".
Ответы
Ответ 1
Сохранение ссылки на функцию извне перед вызовом 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);
Ответ 2
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 только для этого, более того, если он не работает должным образом (и я не думаю, что это так), это не самая яркая вещь, которую вы можете сделать.
Ответ 3
Вот обновленный ответ
var newFunc = oldFunc.bind({}); //clones the function with '{}' acting as it new 'this' parameter
Однако .bind - это новая функция JavaScript, однако есть временное решение из Mdn
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind
Кроме того, он не клонирует дополнительные свойства функции.
Примечание.. Как отметил @gsnedder: приведенный оператор "this" аргумент u (blank {} выше). Будет сохраняться при любых будущих вызовах функции, независимо от перегрузки с помощью функций apply()/call().
Это может быть использовано как в ваших интересах, так и в качестве недостатка в зависимости от того, как вы с ним справляетесь.
Ответ 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);
Ответ 5
(это должен быть только комментарий для Могу ли я копировать/клонировать функцию в JavaScript?... к сожалению, rep < 50 может только опубликовать)
Function.prototype.clone=function(){
return eval( '('+this.toString()+')' );
}
хватает или даже
Object.prototype.clone=function(){
return eval( '('+this.toString()+')' );
}
мысли об эффективности:
- эффективность человека гораздо важнее, чем расточительство человека
ресурсов для оптимизации или улучшения "жизни" машины.
- компьютеры и автоматизированные системы должны сократить человеческие усилия
не увеличивайте его
- вычислительные накладные расходы должны серьезно влиять на привлекательность результата
для потребления человеком многими людьми, чтобы оправдать инвестиции
усилия по оптимизации кода, который часто становится более неясным, тайным и
настолько эзотерическим, что он уже не может быть понят конюшней
программисты после нескольких часов пытаются "понять" логику
при клонировании: этот вопрос может быть довольно риторическим
- Что значит "клонировать" объект javascript? особенно в контексте теории рекурсивных функций
- общая тема для рационализации клонирования заключается в том, что она изолирует и "защищает" создателя от его изменений в doppelgänger.
- if
a = new Object(); b = new Object();
являются a
и b
клоны? как насчет o = Object; a = new o(); b = new o();
- действительно ли это необходимо?
- где заканчивается клонирование? являются прототипными атрибутами
также изолированы, поэтому изменение клонированного объекта не влияет
экземпляры, не связанные с клонированным объектом? в таком случае
клонирование должно пройти весь путь до прототипической цепи до
примитивные конструкторы, которые сами должны быть как-то
клонированный и изолированный (один трюк в браузере - это открыть новое окно и переписать его с помощью оговорки, что
opener .
и т.д. все еще могут протекать поперечные эффекты).
Ответ 6
если вы хотите клонировать функцию, попробуйте следующее:
Function.prototype.clone=function(){
return eval('['+this.toString()+']')[0];
}
Ответ 7
Похоже, нет лучшего способа. Я думаю, вы могли бы попробовать создать пользовательскую требуемую функцию для своего, например:
jQuery.validator.addMethod("customRequired", function(value, element, param) {
return myRequired(value, element, param);
}, jQuery.validator.messages.required);
Похоже, вы уже пробовали все остальное. Извиняюсь, если я неправильно понял вопрос.
Ответ 8
Отвечая на предыдущий пост, когда мне нужно разделить функцию конструктора, сохраняя отдельный прототип, я использую оболочку в новой функции:
`
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-машинах.