Qual é a maneira mais rápida de clonar uma função em JavaScript (com ou sem suas propriedades)?
Duas opções que vêm à mente são eval(func.toString())
e function() { return func.apply(..) }
. Mas estou preocupado com o desempenho de eval e o empacotamento tornará a pilha pior e provavelmente degradará o desempenho se aplicado muito ou aplicado a já empacotado.
new Function(args, body)
parece bom, mas como exatamente posso dividir a função existente de forma confiável para args e corpo sem um analisador JS em JS?
Desde já, obrigado.
Atualização: o que quero dizer é ser capaz de fazer
var funcB = funcA.clone(); // where clone() is my extension
funcB.newField = {...}; // without affecting funcA
javascript
function
Andrey Shchekin
fonte
fonte
Respostas:
tente isto:
fonte
Aqui está uma resposta atualizada
No entanto, ".bind" é um recurso moderno (> = iE9) do JavaScript (com uma solução alternativa de compatibilidade do MDN)
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind
Observação: ele não clona as propriedades anexadas adicionais do objeto de função , incluindo a propriedade prototype . Crédito para @jchook
Nota: que a nova função desta variável está presa ao argumento dado em bind (), mesmo em novas chamadas de função apply (). Crédito para @Kevin
Nota: objeto de função vinculada, instanceof trata newFunc / oldFunc como iguais. Crédito para @Christopher
fonte
newFunc
NÃO terá seu próprio protótipo paranew newFunc
instâncias, masoldFunc
sim.var f = function() { console.log('hello ' + this.name) }
quando vinculado a{name: 'Bob'}
imprime 'hello Bob'.f.apply({name: 'Sam'})
também imprimirá 'hello Bob', ignorando o objeto 'this'.function () { [native code] }
vez do conteúdo completo da função.Aqui está uma versão um pouco melhor da resposta de Jared. Quanto mais você clonar, este não terminará com funções profundamente aninhadas. Sempre chama o original.
Além disso, em resposta à resposta atualizada fornecida por pico.creator, é importante notar que a
bind()
função adicionada em Javascript 1.8.5 tem o mesmo problema que a resposta de Jared - ela continuará aninhando causando funções cada vez mais lentas cada vez que é usada.fonte
Sendo curioso, mas ainda incapaz de encontrar a resposta para o tópico de desempenho da pergunta acima, escrevi esta essência para nodejs para testar o desempenho e a confiabilidade de todas as soluções apresentadas (e pontuadas).
Eu comparei os tempos de parede da criação de uma função de clone e a execução de um clone. Os resultados, juntamente com os erros de asserção, estão incluídos no comentário da essência.
Mais meus dois centavos (com base na sugestão do autor):
clone0 cent (mais rápido, mas mais feio):
clone4 cent (mais lento, mas para aqueles que não gostam de eval () para fins que só eles e seus ancestrais conhecem):
Quanto ao desempenho, se eval / new Function for mais lento do que a solução do wrapper (e realmente depende do tamanho do corpo da função), ele fornece um clone de função simples (e eu quero dizer o clone superficial verdadeiro com propriedades, mas estado não compartilhado) sem fuzz desnecessário com propriedades ocultas, funções de invólucro e problemas com pilha.
Além disso, há sempre um fator importante que você precisa levar em consideração: quanto menos código, menos espaços para erros.
A desvantagem de usar a função eval / new é que o clone e a função original irão operar em escopos diferentes. Não funcionará bem com funções que usam variáveis de escopo. As soluções que usam encapsulamento tipo bind são independentes do escopo.
fonte
Object.assign(newfun.prototype, this.prototype);
antes da instrução return (versão limpa), seu método é a melhor resposta.Foi muito emocionante fazer esse método funcionar, então ele faz um clone de uma função usando a chamada de Function.
Algumas limitações sobre fechamentos descritos em Referência de função MDN
Aproveitar.
fonte
Curto e simples:
fonte
fonte
fonte
originalFunction
, mas não executará realmente quando você executarclonedFunction
, o que é inesperado.Esta resposta é para pessoas que veem a clonagem de uma função como a resposta para seu uso desejado, mas que muitos não precisam realmente clonar uma função, porque o que eles realmente querem é simplesmente poder anexar propriedades diferentes à mesma função, mas apenas declare essa função uma vez.
Faça isso criando uma função de criação de função:
Isso não é exatamente o mesmo que você descreveu, no entanto, depende de como você deseja usar a função que deseja clonar. Isso também usa mais memória porque, na verdade, cria várias cópias da função, uma vez por invocação. No entanto, essa técnica pode resolver o caso de uso de algumas pessoas sem a necessidade de uma
clone
função complicada .fonte
Apenas me perguntando - por que você desejaria clonar uma função quando você tem protótipos E pode definir o escopo de uma chamada de função para qualquer coisa que desejar?
fonte
Se você deseja criar um clone usando o construtor Function, algo como isto deve funcionar:
Um teste simples:
No entanto, esses clones perderão seus nomes e escopo para quaisquer variáveis fechadas.
fonte
Impulsionei a resposta de Jared da minha própria maneira:
1) agora ele suporta clonagem de construtores (pode chamar com novos); nesse caso leva apenas 10 argumentos (você pode variar) - devido à impossibilidade de passar todos os argumentos no construtor original
2) tudo está em fechamentos corretos
fonte
arguments[0], arguments[1] /*[...]*/
por que você simplesmente não usa...arguments
? 1) Não há dependência em relação à quantidade de argumentos (aqui limitados a 10) 2) mais curtosEmbora eu nunca recomende usar isso, achei que seria um pequeno desafio interessante chegar a um clone mais preciso pegando algumas das práticas que pareciam ser as melhores e corrigindo-as um pouco. Aqui está o resultado dos logs:
fonte
Esta função clone:
Observe que esta versão executa apenas uma cópia superficial. Se sua função tiver objetos como propriedades, a referência ao objeto original é preservada (mesmo comportamento de Propagação de objeto ou Object.assign). Isso significa que alterar as propriedades profundas na função clonada afetará o objeto referenciado na função original!
fonte