Posso copiar / Clone uma função em JavaScript?
-
22-07-2019 - |
Pergunta
Eu estou usando jQuery com os validadores plugin. Eu gostaria de substituir o validador "necessária" com um dos meus próprios. Esta é fácil:
jQuery.validator.addMethod("required", function(value, element, param) {
return myRequired(value, element, param);
}, jQuery.validator.messages.required);
Até agora, tão bom. Isso funciona muito bem. Mas o que eu realmente quer fazer é chamar a minha função em alguns casos, e o validador padrão para o resto. Infelizmente, isto acaba por ser recursiva:
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);
Eu olhei para o código-fonte para os validadores, e a implementação padrão de "necessária" é definido como um método anônimo em jQuery.validator.messages.required. Portanto, não há outro (não-anônimo) referência à função que eu possa usar.
Armazenar uma referência para a função externamente antes de chamar addMethod e chamando o validador padrão via essa referência não faz diferença.
O que eu realmente preciso fazer é ser capaz de copiar a função validador padrão exigido por valor em vez de por referência. Mas depois de um pouco de pesquisa, eu não consigo descobrir como fazer isso. É possível?
Se for impossível, então eu posso copiar o código fonte para a função original. Mas isso cria um problema de manutenção, e eu preferiria não fazer isso a menos que não há "melhor maneira".
Solução
Armazenar uma referência para a função externamente antes de chamar addMethod e chamando o validador padrão via essa referência não faz diferença.
Isso é exatamente o deve funcionar .
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);
Isso deve funcionar também: (E o problema com this
é resolvido)
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);
Outras dicas
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;
};
A única coisa ruim com isso é que o protótipo não é clonado para que você realmente não pode mudá-lo ... Eu estou trabalhando em uma maneira de clonar qualquer tipo de objetos e eu só tenho RegExp resta a fazer. Então eu provavelmente vou editar amanhã e colocar todo o código (que é tipo de muito tempo e não é otimizado, se você usá-lo apenas para as funções e objetos.
E a comentar outras respostas, usando eval () é totalmente estúpido e é um caminho muito longo e o construtor Function é uma espécie do mesmo. Literrals são muito melhores. E incluindo JQuery apenas para que, além disso, se ele não funcionar corretamente (e eu não acho que ele faz) não é a coisa mais brilhante que você pode fazer.
Aqui está uma resposta atualizada
var newFunc = oldFunc.bind({}); //clones the function with '{}' acting as it's new 'this' parameter
No entanto .bind é um novo recurso de JavaScript não é, contudo, uma solução de Mdn
https://developer.mozilla.org/en/JavaScript/ referência / Global_Objects / Função / bind
Além disso, ele não clonar as funções propriedades adicionais.
Nota: Como @gsnedder apontadas: a declaração bound "este" argumento u fornecido (em branco {} acima). Persistirá para futuras chamadas da função, independentemente do excesso de equitação através da apply () / call () funções.
Isto pode ser usado tanto para a sua vantagem, ou desvantagem, dependendo de como você lida com isso.
Eu acho que você está apenas perdendo um pouco do escopo. Tente isto:
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);
(este deve ser apenas um comentário a Can eu copiar / clone uma função em JavaScript? ... infelizmente, com rep <50 só pode postar)
Function.prototype.clone=function(){
return eval( '('+this.toString()+')' );
}
basta, ou mesmo
Object.prototype.clone=function(){
return eval( '('+this.toString()+')' );
}
pensamentos sobre a eficiência:
- eficiência humana é muito mais importante do que desperdiçar humana recursos para otimizar ou melhorar a "vida" de uma máquina
- computadores e sistemas automatizados são supostamente para reduzir o esforço humano não aumentá-la
- sobrecarga computacional deve afetar seriamente a palatabilidade de um resultado para consumo humano, por muitas muitas pessoas, para justificar o investimento esforço na otimização de código que muitas vezes se torna mais obscuro, misterioso e tão esotéricos que já não pode ser entendido por um estábulo de programadores após horas de tentar "compreender" a lógica
sobre a clonagem: esta questão pode ser bastante retórica
- o que significa a "clone" um objeto javascript? especialmente no contexto da teoria função recursiva
- um tema comum a clonagem racionalizar é que ela isola e "protege" um criador de suas mudanças Doppelganger
- Se
a = new Object(); b = new Object();
sãoa
eb
clones? como sobreo = Object; a = new o(); b = new o();
- é realmente necessário?
- onde é que a clonagem de parada? são os atributos protótipo para ser
isolado também para a mudança de um objeto clonado delas não afeta
exemplos não associado com o objeto clonado? em cujo caso
clonagem deve percorrer todo o caminho até a cadeia protótipo do
construtores primitivas que se teriam de ser de alguma forma
clonada e isolada (um truque em um navegador é abrir uma nova janela e preenchê-la novamente com a ressalva de que
opener .
etc. ainda pode vazar efeitos cruzados)
Se você deseja clonar uma função, tente o seguinte:
Function.prototype.clone=function(){
return eval('['+this.toString()+']')[0];
}
Parece que não há nenhuma 'maneira melhor'. Eu acho que você pode tentar fazer uma função requerida sob encomenda para seu próprio exemplo:
jQuery.validator.addMethod("customRequired", function(value, element, param) {
return myRequired(value, element, param);
}, jQuery.validator.messages.required);
Parece que você já tentou de tudo. Desculpas se eu não entendi a pergunta.
Respondendo a post anterior, quando eu preciso compartilhar uma função construtora, mantendo protótipo distinta, eu uso um invólucro em uma nova função:
`
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'};
`
Eu corro vários testes para verificar que isso não execução lenta em motores de boas JS.