Подтвердить что ты не робот

Могу ли я копировать/клонировать функцию в 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 и вызовом валидатора по умолчанию через эту ссылку не имеет значения.

Мне действительно нужно сделать, чтобы иметь возможность копировать требуемую по умолчанию функцию валидатора по значению, а не по ссылке. Но после довольно многого поиска я не могу понять, как это сделать. Возможно ли это?

Если это невозможно, я могу скопировать источник исходной функции. Но это создает проблему обслуживания, и я бы предпочел не делать этого, если нет "лучшего способа".

4b9b3361

Ответ 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-машинах.