AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / coding / Perguntas / 79574309
Accepted
FaniX
FaniX
Asked: 2025-04-15 11:04:19 +0800 CST2025-04-15 11:04:19 +0800 CST 2025-04-15 11:04:19 +0800 CST

Como fazer uma cópia de uma função?

  • 772

Em javascript, quero fazer uma cópia (superficial) de um Function, para que as propriedades do novo objeto não sejam afetadas pelo objeto original:

function func(...) { ... } // to say, function func(x, y) { return [x,y] }
func.a = 1
let func1 = func       // without copy, func1 and func IS the same object
let func2 = copy(func) // need to be implemented

func.a = 2
func1.a        // becomes 2
func2.a        // shall still be 1
func2("abc")   // shall return the same result as func("abc")

É possível?


A melhor maneira que encontrei no momento é definir uma função wrapper:

function f0(x, y) { return [x,y] }
f0.a = 1

function copy(fn){
  function wrapper(){
    return fn.apply(wrapper, arguments)
  }
  Object.assign(wrapper,fn)
  return wrapper
}

let f2 = copy(f0)

f0.a = 2
f2.a        // is still 1
f0.length   // gives 2
f2.length   // gives 0

Entretanto, há alguns problemas com esta solução:

  1. A aplicação em cadeia de copylevará a vários níveis de wrapper. por exemplo, copy(copy(copy(fn)))retornará uma função com três wrappers.
  2. a lengthfunção de origem é perdida, wrapper.lengthé sempre 0.
javascript
  • 2 2 respostas
  • 107 Views

2 respostas

  • Voted
  1. Best Answer
    Bergi
    2025-04-15T17:08:38+08:002025-04-15T17:08:38+08:00

    há alguns problemas com esta solução

    Os principais problemas que vejo são

    • Por alguma razão você escolheu aplicar o fnao wrapper, não aothis
    • Object.assigncopia apenas as propriedades enumeráveis ​​(próprias) e apenas seus valores. (Isso inclui seu problema com .length, mas também com .name, e, claro, outras propriedades personalizadas)
    • A nova função herda de Function.prototype, ela não necessariamente tem o mesmo protótipo que fn.

    A aplicação em cadeia de cópias levará a vários níveis de wrapper.

    Isso não é necessariamente inesperado. Mas se você quisesse resolver isso, precisaria de uma maneira de extrair o original fnde qualquer função wrapper; isso pode ser feito usando um WeakMap.

    const originals = new WeakMap();
    function copy(source) {
      const fn = originals.get(source) ?? source;
      const target = function() {
        return fn.apply(this, arguments);
      };
      originals.set(target, fn);
      Object.setPrototypeOf(target, Object.getPrototypeOf(source));
      Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
      return target;
    }
    
    • 2
  2. TechnoTech
    2025-04-15T13:08:15+08:002025-04-15T13:08:15+08:00

    Para fazer uma cópia superficial de uma função (ou seja, copiar seu comportamento invocável e suas próprias propriedades), você precisará fazer algumas coisas:

    Crie uma nova função que se comporte da mesma maneira.

    Copie as propriedades enumeráveis ​​próprias da função original.

    function copy(originalFn) {
      // Create a new function that calls the original
      const copiedFn = function(...args) {
        return originalFn.apply(this, args);
      };
    
      // Copy own enumerable properties (shallow)
      Object.keys(originalFn).forEach(key => {
        copiedFn[key] = originalFn[key];
      });
    
      return copiedFn;
    }
    

    EDITADO:

    conforme sugerido acima, a solução tem problemas de múltiplos wrappers e o comprimento é perdido, pois a nova função é variável((...args))

    então agora o que podemos fazer é reconstruir a função usando sua representação de string, isso evitará cadeias de wrapper profundas.

    NOTA: esta solução tem a limitação de que não funcionará para funções nativas que não podem ser transformadas em strings, por exemplo, funções vinculadas, fechamentos com dependências externas, mas funcionará para funções simples

    function copy(originalFn) {
      const fnStr = originalFn.toString();
      let copiedFn;
      try {
        copiedFn = new Function('return ' + fnStr)();
      } catch (e) {
        throw new Error('Failed to copy function: ' + e.message);
      }
    
      Object.keys(originalFn).forEach(key => {
        copiedFn[key] = originalFn[key];
      });
    
      return copiedFn;
    }
    
    //example
    function func(x, y) { return [x, y]; }
    func.a = 1;
    
    let func2 = copy(copy(func));
    
    console.log(func2(1, 2)); // [1, 2]
    console.log(func2.length); // 2
    console.log(func2.a); // 1

    • -2

relate perguntas

  • classificação de mesclagem não está funcionando - código Javascript: não é possível encontrar o erro mesmo após a depuração

  • método select.remove() funciona estranho [fechado]

  • Sempre um 401 res em useOpenWeather () - react-open-weather lib [duplicado]

  • O elemento de entrada não possui atributo somente leitura, mas os campos ainda não podem ser editados [fechado]

  • Como editar o raio do primeiro nó de um RadialTree D3.js?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Reformatar números, inserindo separadores em posições fixas

    • 6 respostas
  • Marko Smith

    Por que os conceitos do C++20 causam erros de restrição cíclica, enquanto o SFINAE antigo não?

    • 2 respostas
  • Marko Smith

    Problema com extensão desinstalada automaticamente do VScode (tema Material)

    • 2 respostas
  • Marko Smith

    Vue 3: Erro na criação "Identificador esperado, mas encontrado 'import'" [duplicado]

    • 1 respostas
  • Marko Smith

    Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores?

    • 1 respostas
  • Marko Smith

    Como faço para corrigir um erro MODULE_NOT_FOUND para um módulo que não importei manualmente?

    • 6 respostas
  • Marko Smith

    `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso?

    • 3 respostas
  • Marko Smith

    Um programa vazio que não faz nada em C++ precisa de um heap de 204 KB, mas não em C

    • 1 respostas
  • Marko Smith

    PowerBI atualmente quebrado com BigQuery: problema de driver Simba com atualização do Windows

    • 2 respostas
  • Marko Smith

    AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos

    • 1 respostas
  • Martin Hope
    Fantastic Mr Fox Somente o tipo copiável não é aceito na implementação std::vector do MSVC 2025-04-23 06:40:49 +0800 CST
  • Martin Hope
    Howard Hinnant Encontre o próximo dia da semana usando o cronógrafo 2025-04-21 08:30:25 +0800 CST
  • Martin Hope
    Fedor O inicializador de membro do construtor pode incluir a inicialização de outro membro? 2025-04-15 01:01:44 +0800 CST
  • Martin Hope
    Petr Filipský Por que os conceitos do C++20 causam erros de restrição cíclica, enquanto o SFINAE antigo não? 2025-03-23 21:39:40 +0800 CST
  • Martin Hope
    Catskul O C++20 mudou para permitir a conversão de `type(&)[N]` de matriz de limites conhecidos para `type(&)[]` de matriz de limites desconhecidos? 2025-03-04 06:57:53 +0800 CST
  • Martin Hope
    Stefan Pochmann Como/por que {2,3,10} e {x,3,10} com x=2 são ordenados de forma diferente? 2025-01-13 23:24:07 +0800 CST
  • Martin Hope
    Chad Feller O ponto e vírgula agora é opcional em condicionais bash com [[ .. ]] na versão 5.2? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench Por que um traço duplo (--) faz com que esta cláusula MariaDB seja avaliada como verdadeira? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng Por que `dict(id=1, **{'id': 2})` às vezes gera `KeyError: 'id'` em vez de um TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos 2024-03-20 03:12:31 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve