Каков самый быстрый способ клонировать функцию в JavaScript (с ее свойствами или без них)?
На ум приходят два варианта: eval(func.toString())
а function() { return func.apply(..) }
. Но меня беспокоит производительность eval, и упаковка ухудшит стек и, вероятно, снизит производительность, если применяется много или применяется к уже упакованной.
new Function(args, body)
выглядит красиво, но как я могу надежно разделить существующую функцию на аргументы и тело без парсера JS в JS?
Заранее спасибо.
Обновление: я имею в виду, что могу делать
var funcB = funcA.clone(); // where clone() is my extension
funcB.newField = {...}; // without affecting funcA
javascript
function
Андрей Щекин
источник
источник
Ответы:
попробуй это:
источник
Вот обновленный ответ
Однако
.bind
это современная (> = iE9) функция JavaScript (с обходным путем совместимости от MDN )Ноты
Это не клон объекта функции дополнительные присоединенные свойства , в том числе и в прототипе собственности. Кредит для @jchook
В новой функции эта переменная застревает с аргументом, указанным в bind (), даже при вызове новой функции apply (). Кредит @Kevin
источник
newFunc
НЕ будет собственного прототипа дляnew newFunc
экземпляров, аoldFunc
будет.var f = function() { console.log('hello ' + this.name) }
при привязке{name: 'Bob'}
печатает «привет, Боб».f.apply({name: 'Sam'})
также напечатает "hello Bob", игнорируя объект "this".function () { [native code] }
вместо полного содержимого функции.Вот немного лучшая версия ответа Джареда. Чем больше вы клонируете, тем больше у этого не будет глубоко вложенных функций. Всегда называет оригинал.
Кроме того, в ответ на обновленный ответ, данный pico.creator, стоит отметить, что
bind()
функция, добавленная в Javascript 1.8.5, имеет ту же проблему, что и ответ Джареда - она будет продолжать вложение, вызывая все более и более медленные функции каждый раз, когда она используется.источник
Из-за любопытства, но все еще неспособного найти ответ на тему производительности вопроса выше, я написал эту суть для nodejs, чтобы проверить как производительность, так и надежность всех представленных (и оцененных) решений.
Я сравнил настенное время создания функции клона и выполнения клона. Результаты вместе с ошибками утверждения включены в суть комментария.
Плюс мои два цента (по предложению автора):
clone0 cent (быстрее, но уродливее):
clone4 cent (медленнее, но для тех, кто не любит eval () для целей, известных только им и их предкам):
Что касается производительности, если eval / new Function работает медленнее, чем решение-оболочка (и это действительно зависит от размера тела функции), он дает вам голый клон функции (и я имею в виду настоящий мелкий клон со свойствами, но неразделенным состоянием) без ненужного пуха со скрытыми свойствами, функциями-оболочками и проблемами со стеком.
К тому же всегда есть один важный фактор, который нужно учитывать: чем меньше кода, тем меньше мест для ошибок.
Обратной стороной использования функции eval / new является то, что клон и исходная функция будут работать в разных областях. Это не будет хорошо работать с функциями, которые используют переменные с ограниченным объемом. Решения, использующие привязку, подобную связыванию, не зависят от области действия.
источник
Object.assign(newfun.prototype, this.prototype);
перед оператором return (чистая версия), ваш метод - лучший ответ.Было довольно интересно заставить этот метод работать, поэтому он создает клон функции с помощью вызова функции.
Некоторые ограничения закрытий, описанные в Справочнике по функциям MDN
Наслаждаться.
источник
Коротко и просто:
источник
источник
источник
originalFunction
, но на самом деле не будет выполняться при запускеclonedFunction
, что неожиданно.Этот ответ предназначен для людей, которые рассматривают клонирование функции как ответ на желаемое использование, но многим на самом деле не нужно клонировать функцию, потому что на самом деле они хотят просто иметь возможность присоединять разные свойства к одной и той же функции, но только объявите эту функцию один раз.
Сделайте это, создав функцию создания функции:
Это не совсем то же самое, что вы описали, однако это зависит от того, как вы хотите использовать функцию, которую хотите клонировать. Это также использует больше памяти, поскольку фактически создает несколько копий функции, по одному разу за вызов. Однако этот метод может помочь в решении некоторых вариантов использования без необходимости использования сложной
clone
функции.источник
Просто интересно - зачем вам клонировать функцию, если у вас есть прототипы и вы можете установить область действия вызова функции на все, что захотите?
источник
Если вы хотите создать клон с помощью конструктора Function, должно сработать что-то вроде этого:
Простой тест:
Однако эти клоны потеряют свои имена и область действия для любых закрытых переменных.
источник
Я по-своему усложнил ответ Джареда:
1) теперь поддерживает клонирование конструкторов (можно вызывать с помощью new); в этом случае принимает только 10 аргументов (вы можете изменять это) - из-за невозможности передать все аргументы в исходный конструктор
2) все в правильном закрытии
источник
arguments[0], arguments[1] /*[...]*/
, чтобы просто не использовать...arguments
? 1) Нет зависимости относительно количества аргументов (здесь ограничено 10) 2) корочеХотя я бы никогда не рекомендовал использовать это, я подумал, что будет интересной небольшой задачей придумать более точный клон, взяв некоторые из приемов, которые казались лучшими, и немного его исправили. Вот результат журналов:
источник
Эта функция клонирования:
Обратите внимание, что эта версия выполняет только поверхностное копирование. Если ваша функция имеет объекты как свойства, ссылка на исходный объект сохраняется (такое же поведение, как Object spread или Object.assign). Это означает, что изменение глубоких свойств в клонированной функции повлияет на объект, на который есть ссылка в исходной функции!
источник