Могу ли я скопировать / клонировать функцию в 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);

Я просмотрел исходный код валидаторов, и реализация по умолчанию «required» определена как анонимный метод в jQuery.validator.messages.required. Таким образом, нет другой (не анонимной) ссылки на функцию, которую я могу использовать.

Сохранение ссылки на функцию извне перед вызовом addMethod и вызов валидатора по умолчанию через эту ссылку не имеет значения.

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

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

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
21
0
29 414
8
Перейти к ответу Данный вопрос помечен как решенный

Ответы 8

Похоже, лучшего пути нет. Я думаю, вы могли бы попробовать создать собственную требуемую функцию для себя, например:

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

Похоже, вы уже пробовали все остальное. Прошу прощения, если я неправильно понял вопрос.

Ответ принят как подходящий

Storing a reference to the function externally before calling addMethod and calling the default validator via that reference makes no difference.

Это именно то, что должно сработать.

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

Он исправляет рекурсию (с учетом этого, не знаю, почему у меня этого не произошло, поскольку я использовал var oldRequired вместо jvmoldrequired, но в остальном был идентичен, но теперь внутри oldRequired «this» неверно. Я буду работать над этим, но спасибо, я думаю, что сейчас я на правильном пути.

Craig Stuntz 15.01.2009 20:58

Совет crescentfresh исправляет "это".

Craig Stuntz 15.01.2009 21:05

Но это не лучшее решение. Лучше всего использовать var oldRequired (не знаю, почему это не работает!) И oldRequired.call (jQuery.validator.methods,…,…,…)

Georg Schölly 15.01.2009 22:01

Я думаю, вы просто упускаете из виду. Попробуй это:

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

Да, это решает проблему «этого». Спасибо за это!

Craig Stuntz 15.01.2009 21:04

если вы хотите клонировать функцию, попробуйте следующее:

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

Отвечая на предыдущий пост, когда мне нужно поделиться функцией конструктора, сохраняя отдельный прототип, я использую оболочку в новой функции:

`

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-движках.

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 () совершенно глупо и слишком долго, а конструктор функций такой же. Литералы намного лучше. И включение 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 ().

Это может быть использовано как в вашу пользу, так и в ущерб в зависимости от того, как вы с этим справляетесь.

Однако он полагается на то, что вы всегда хотите вызывать функцию с тем же thisArg.

gsnedders 08.04.2013 22:57

@gsnedders: Нет, аргумент this для клонированной функции может быть определен. Это первый параметр функции привязки. Однако это может быть обоюдоострый меч. В то время как он обеспечивает согласованность «this» с одним заранее определенным объектом, независимо от того, как вы передаете и выполняете функцию. Вы не можете вернуть аргумент this к объекту, из которого вы вызываете (при условии, что он другой). Если вы не переопределите его снова, с помощью apply (). В конце концов, варианты хороши, если вы знаете, что делаете. А как была сделана ваша функция, это не должно быть проблемой.

PicoCreator 10.04.2013 09:40

Да, это можно определить. Как я уже сказал, «с таким же». Однако вы не можете переопределить его с помощью apply, поскольку связанная функция всегда использует привязку this.

gsnedders 10.04.2013 16:49

@gsnedders: Точка взята, протестирована, и вы правы с применением, а не с перебором (хром). Обновлен ответ, чтобы сделать этот довольно важный момент более очевидным.

PicoCreator 11.04.2013 08:41

(это должен быть только комментарий для Могу ли я скопировать / клонировать функцию в 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 и b? как насчет o = Object; a = new o(); b = new o();
  • это действительно необходимо?
  • где заканчивается клонирование? являются прототипными атрибутами, которые должны быть изолированы, поэтому их изменение клонированным объектом не влияет экземпляры, не связанные с клонированным объектом? в таком случае клонирование должно идти по всей цепочке прототипов до примитивные конструкторы, которые сами должны быть как-то клонированный и изолированный (одна уловка в браузере - открыть новое окно и повторно заполнить его с оговоркой, что opener . и т. д. все еще могут пропускать перекрестные эффекты)

Другие вопросы по теме