Qual é a melhor maneira de falsificar a sobrecarga de funções em Javascript?
Eu sei que não é possível sobrecarregar funções em Javascript como em outros idiomas. Se eu precisasse de uma função com dois usos foo(x)
e foo(x,y,z)
qual a melhor / preferida:
- Usando nomes diferentes em primeiro lugar
- Usando argumentos opcionais como
y = y || 'default'
- Usando número de argumentos
- Verificando tipos de argumentos
- Ou como?
javascript
overloading
hamdiakoguz
fonte
fonte
Respostas:
A melhor maneira de sobrecarregar a função com parâmetros não é verificar o comprimento do argumento ou os tipos; verificar os tipos apenas tornará seu código lento e você se divertirá com matrizes, nulos, objetos etc.
O que a maioria dos desenvolvedores faz é aderir a um objeto como o último argumento para seus métodos. Este objeto pode conter qualquer coisa.
Então você pode lidar com isso da maneira que quiser no seu método. [Switch, if-else, etc.]
fonte
if(opts['test']) //if test param exists, do something.. if(opts['bar']) //if bar param exists, do something
arguments.length
não é recomendada? Além disso, eu já estive aqui antes e li O que a maioria dos desenvolvedores faz é ... , mas tenho certeza de que este é o único lugar em que eu já vi isso. Esse método também estraga a açucaridade sintática de ter 'sobrecargas'!Costumo fazer isso:
C #:
Equivalente a JavaScript:
Este exemplo em particular é realmente mais elegante em javascript que em c #. Os parâmetros não especificados são 'indefinidos' em javascript, que são avaliados como falsos em uma instrução if. No entanto, a definição da função não transmite a informação de que p2 e p3 são opcionais. Se você precisar de muita sobrecarga, o jQuery decidiu usar um objeto como parâmetro, por exemplo, jQuery.ajax (opções). Concordo com eles que essa é a abordagem mais poderosa e claramente documentável para sobrecarga, mas raramente preciso de mais de um ou dois parâmetros opcionais rápidos.
EDIT: teste IF alterado por sugestão de Ian
fonte
undefined
em JS, nãonull
. Como prática recomendada, você nunca deve definir nadaundefined
, portanto, isso não deve ser um problema, desde que você altere seu teste parap2 === undefined
.false
como o último argumento, ele não concatenará"false"
até o final, porque oif(p3)
não será ramificado.typeof p2 === "undefined"
provavelmente é o inverso do que você está esperando na instância do seu exemplo, eu achotypeof p2 !== "undefined"
que é o que você pretendia. Além disso, posso sugerir sendo seu suposto corda concatenate, número e booleano que você realmente fazp2 === "number"; p3 === "boolean"
===
e!==
? Por que não apenas usar==
e!=
?Não há nenhuma função real sobrecarregando no JavaScript, pois ele permite passar qualquer número de parâmetros de qualquer tipo. Você deve verificar dentro da função quantos argumentos foram passados e que tipo eles são.
fonte
A resposta correta é NÃO HÁ SOBRECARGA NO JAVASCRIPT.
A verificação / mudança dentro da função não está sobrecarregada.
O conceito de sobrecarga: Em algumas linguagens de programação, sobrecarga de função ou sobrecarga de método é a capacidade de criar vários métodos com o mesmo nome com diferentes implementações. As chamadas para uma função sobrecarregada executarão uma implementação específica dessa função apropriada ao contexto da chamada, permitindo que uma chamada de função execute tarefas diferentes, dependendo do contexto.
Por exemplo, doTask () e doTask (objeto O) são métodos sobrecarregados. Para chamar o último, um objeto deve ser passado como parâmetro, enquanto o primeiro não requer um parâmetro e é chamado com um campo de parâmetro vazio. Um erro comum seria atribuir um valor padrão ao objeto no segundo método, o que resultaria em um erro de chamada ambíguo, pois o compilador não saberia qual dos dois métodos usar.
https://en.wikipedia.org/wiki/Function_overloading
Todas as implementações sugeridas são ótimas, mas, verdade seja dita, não há implementação nativa para JavaScript.
fonte
Há duas maneiras de abordar isso melhor:
Passe um dicionário (array associativo) se quiser deixar muita flexibilidade
Pegue um objeto como argumento e use herança baseada em protótipo para adicionar flexibilidade.
fonte
Aqui está uma abordagem que permite a sobrecarga real de métodos usando tipos de parâmetros, mostrados abaixo:
Edit (2018) : desde que foi escrito em 2011, a velocidade das chamadas diretas ao método aumentou bastante, enquanto a velocidade dos métodos sobrecarregados não.
Não é uma abordagem que eu recomendaria, mas é um exercício de reflexão que vale a pena pensar em como você pode resolver esses tipos de problemas.
Aqui está uma referência das diferentes abordagens - https://jsperf.com/function-overloading . Ele mostra que a sobrecarga de funções (levando em consideração os tipos) pode ser cerca de 13 vezes mais lenta no V8 do Google Chrome a partir de 16.0 (beta) .
Além de passar um objeto (ie
{x: 0, y: 0}
), também é possível adotar a abordagem C quando apropriado, nomeando os métodos de acordo. Por exemplo, Vector.AddVector (vector), Vector.AddIntegers (x, y, z, ...) e Vector.AddArray (integerArray). Você pode olhar para as bibliotecas C, como o OpenGL, para inspirar nomes.Editar : eu adicionei uma referência para passar um objeto e testá-lo usando ambos
'param' in arg
earg.hasOwnProperty('param')
, e a sobrecarga de função é muito mais rápida do que passar um objeto e verificar propriedades (pelo menos nesta referência).Do ponto de vista do projeto, a sobrecarga de função é válida ou lógica apenas se os parâmetros sobrecarregados corresponderem à mesma ação. Portanto, é lógico que deve haver um método subjacente que se preocupe apenas com detalhes específicos, caso contrário isso pode indicar escolhas inadequadas de design. Portanto, também se pode resolver o uso de sobrecarga de função convertendo dados em um objeto respectivo. É claro que é preciso considerar o escopo do problema, pois não há necessidade de criar designs elaborados se a sua intenção é apenas imprimir um nome, mas para o design de estruturas e bibliotecas esse pensamento é justificado.
Meu exemplo vem de uma implementação de retângulo - daí a menção de dimensão e ponto. Talvez Retângulo poderia adicionar um
GetRectangle()
método para oDimension
ePoint
protótipo, e, em seguida, a função de sobrecarga questão está classificada. E quanto aos primitivos? Bem, temos o comprimento do argumento, que agora é um teste válido, já que os objetos têm umGetRectangle()
método.fonte
A melhor maneira realmente depende da função e dos argumentos. Cada uma das suas opções é uma boa ideia em diferentes situações. Geralmente, eu tento isso na seguinte ordem até que um deles funcione:
Usando argumentos opcionais como y = y || 'padrão'. Isso é conveniente se você pode fazê-lo, mas nem sempre funciona na prática, por exemplo, quando 0 / nulo / indefinido seria um argumento válido.
Usando número de argumentos. Semelhante à última opção, mas pode funcionar quando o número 1 não funcionar.
Verificando tipos de argumentos. Isso pode funcionar em alguns casos em que o número de argumentos é o mesmo. Se você não pode determinar com segurança os tipos, pode ser necessário usar nomes diferentes.
Usando nomes diferentes em primeiro lugar. Pode ser necessário fazer isso se as outras opções não funcionarem, não forem práticas ou para consistência com outras funções relacionadas.
fonte
O problema é que o JavaScript NÃO suporta nativamente a sobrecarga de métodos. Portanto, se ele vê / analisa duas ou mais funções com o mesmo nome, apenas considera a última função definida e sobrescreve as anteriores.
Uma das maneiras que considero adequadas para a maioria dos casos é a seguinte -
Vamos dizer que você tem método
Em vez de sobrecarregar o método que não é possível em javascript, você pode definir um novo método
e modifique a 1ª função da seguinte maneira -
Se você tiver muitos desses métodos sobrecarregados, considere usar
switch
apenasif-else
declarações.( mais detalhes )
PS: O link acima vai para o meu blog pessoal, com detalhes adicionais.
fonte
Não tenho certeza sobre as melhores práticas, mas eis como faço:
fonte
Eu apenas tentei isso, talvez atenda às suas necessidades. Dependendo do número dos argumentos, você pode acessar uma função diferente. Você o inicializa na primeira vez que o chama. E o mapa de funções está oculto no fechamento.
Teste-o.
fonte
Como o JavaScript não possui opções de sobrecarga de função, o objeto pode ser usado. Se houver um ou dois argumentos obrigatórios, é melhor mantê-los separados do objeto de opções. Aqui está um exemplo de como usar o objeto de opções e os valores preenchidos para o valor padrão, caso o valor não tenha sido passado no objeto de opções.
Aqui está um exemplo de como usar o objeto de opções
fonte
Não há como funcionar sobrecarregando em javascript. Portanto, recomendo o seguinte pelo
typeof()
método, em vez de múltiplas funções, para a sobrecarga falsa.Boa sorte!
fonte
var type = typeof param; if (type === 'string') ...
INTRODUÇÃO
Até agora, ler tantas respostas daria dor de cabeça a qualquer um. Qualquer pessoa que tente conhecer o conceito precisará conhecer os seguintes pré-requisitos .
Function overloading Definition
,Function Length property
,Function argument property
Function overloading
em sua forma mais simples, significa que uma função executa tarefas diferentes com base no número de argumentos que estão sendo transmitidos para ela. Notavelmente, a TASK1, TASK2 e TASK3 estão destacadas abaixo e estão sendo executadas com base no número dearguments
passadas para a mesma funçãofooYo
.OBSERVAÇÃO - JS não fornece capacidade embutida de sobrecarga de função.
Alternativa
John E Resig (criador do JS) apontou uma alternativa que usa os pré-requisitos acima para obter a capacidade de implementar a sobrecarga de funções.
O código abaixo usa uma abordagem simples, mas ingênua, usando
if-else
ouswitch
instruçãoargument-length
propriedade.Outra técnica é muito mais limpa e dinâmica. O destaque dessa técnica é a
addMethod
função genérica.definimos uma função
addMethod
que é usada para adicionar funções diferentes a um objeto com o mesmo nome, mas com funcionalidades diferentes .abaixo, a
addMethod
função aceita três parâmetros de nome de objetoobject
, nomename
da função e a função que queremos que seja chamadafn
.addMethod
definição internavar old
armazena a referência à anteriorfunction
sendo armazenada com a ajuda do fechamento - uma bolha protetora.addMethod
adiciona três funções que, quando invocadas usandoninja.whatever(x)
o número de argumentosx
que podem ser qualquer coisa, ou seja, em branco ou uma ou mais de uma, invocam funções diferentes, conforme definido ao usar aaddMethod
função.fonte
Outra maneira de abordar isso é usando a variável especial: argumentos , esta é uma implementação:
para que você possa modificar esse código para:
fonte
Veja isso. É muito legal http://ejohn.org/blog/javascript-method-overloading/ Truque o Javascript para permitir que você faça chamadas assim:
fonte
Func(new Point())
eFunc(new Rectangle())
executarei funções diferentes. Mas devo salientar que este é um hack sujo, pois a sobrecarga de método é realmente uma tarefa em tempo de compilação, não em tempo de execução.Função sobrecarga em Javascript:
Sobrecarga de função é a capacidade de uma linguagem de programação criar várias funções com o mesmo nome com diferentes implementações. quando uma função sobrecarregada é chamada, ela executará uma implementação específica dessa função, apropriada ao contexto da chamada. Esse contexto geralmente é a quantidade de argumentos recebidos e permite que uma chamada de função se comporte de maneira diferente, dependendo do contexto.
Javascript não possui sobrecarga de função embutida. No entanto, esse comportamento pode ser emulado de várias maneiras. Aqui está um simples e conveniente:
Em cenários em que você não sabe quantos argumentos estará recebendo, pode usar o operador resto, que é de três pontos
...
. Ele converterá o restante dos argumentos em uma matriz. Cuidado com a compatibilidade do navegador. Aqui está um exemplo:fonte
Como este post já contém muitas soluções diferentes, pensei em publicar outro.
isso pode ser usado como mostrado abaixo:
Esta solução não é perfeita, mas quero apenas demonstrar como isso pode ser feito.
fonte
Você pode usar o 'addMethod' de John Resig. Com esse método, você pode "sobrecarregar" os métodos com base na contagem de argumentos.
Eu também criei uma alternativa para esse método que usa o cache para armazenar as variações da função. As diferenças são descritas aqui
fonte
Padrão de encaminhamento => a melhor prática para sobrecarga de JS
Encaminhar para outra função cujo nome é construído a partir dos 3º e 4º pontos:
Aplicação no seu caso:
Outra amostra complexa:
fonte
Função Sobrecarga via Polimorfismo Dinâmico em 100 linhas de JS
Esta é a partir de um conjunto maior de código que inclui os
isFn
,isArr
etc. funções de controlo do tipo. A versão do VanillaJS abaixo foi reformulada para remover todas as dependências externas; no entanto, você terá que definir suas próprias funções de verificação de tipo para uso nas.add()
chamadas.Nota: Esta é uma função de execução automática (para que possamos ter um escopo de fechamento / fechamento), daí a atribuição para, em
window.overload
vez defunction overload() {...}
.Uso:
O chamador define suas funções sobrecarregadas atribuindo uma variável ao retorno de
overload()
. Graças ao encadeamento, as sobrecargas adicionais podem ser definidas em série:O argumento opcional único para
overload()
definir a função "padrão" a ser chamada se a assinatura não puder ser identificada. Os argumentos para.add()
são:fn
:function
definindo a sobrecarga;a_vArgumentTests
:Array
defunction
s definindo os testes a serem executados noarguments
. Cadafunction
um aceita um único argumento e retornatrue
thy com base em se o argumento é válido;sAlias
(Opcional):string
definir o alias para acessar diretamente a função de sobrecarga (fn
), por exemplomyOverloadedFn.noArgs()
, chamará essa função diretamente, evitando os testes de polimorfismo dinâmico dos argumentos.Essa implementação, na verdade, permite mais do que apenas sobrecargas de funções tradicionais, pois o segundo
a_vArgumentTests
argumento.add()
na prática define tipos personalizados. Portanto, você pode bloquear argumentos não apenas com base no tipo, mas também em intervalos, valores ou coleções de valores!Se você procurar nas 145 linhas de código,
overload()
verá que cada assinatura é categorizada pelo número dearguments
passadas para ela. Isso é feito para limitar o número de testes que estamos executando. Também acompanho uma contagem de chamadas. Com algum código adicional, as matrizes de funções sobrecarregadas podem ser re-classificadas para que as funções chamadas mais comuns sejam testadas primeiro, adicionando novamente alguma medida de aprimoramento de desempenho.Agora, existem algumas advertências ... Como o Javascript é pouco digitado, você deve ter cuidado com o
vArgumentTests
queinteger
pode ser validado como umfloat
, etc.Versão JSCompress.com (1114 bytes, 744 bytes compactados em g):
fonte
Agora você pode sobrecarregar as funções no ECMAScript 2018 sem polyfills, verificando o comprimento / tipo do var, etc., basta usar a sintaxe de dispersão .
O que é sintaxe de propagação?
Nota: a sintaxe de propagação em literais de objetos não funciona no Edge e no IE e é um recurso experimental. veja compatibilidade do navegador
fonte
Algo assim pode ser feito para sobrecarga de funções.
Fonte
fonte
Esta é uma pergunta antiga, mas acho que precisa de outra entrada (embora eu duvide que alguém a leia). O uso de Expressões de Função Imediatamente Invocadas (IIFE) pode ser usado em conjunto com fechamentos e funções em linha para permitir a sobrecarga de funções. Considere o seguinte exemplo (artificial):
Em resumo, o uso do IIFE cria um escopo local, permitindo definir a variável privada
old
para armazenar uma referência à definição inicial da funçãofoo
. Essa função então retorna uma função embutidanewFoo
que registra o conteúdo dos dois argumentos se for passado exatamente dois argumentosa
eb
ou chama aold
função ifarguments.length !== 2
. Esse padrão pode ser repetido várias vezes para dotar uma variável de várias defesas funcionais diferentes.fonte
Eu gostaria de compartilhar um exemplo útil de abordagem do tipo sobrecarregado.
Uso: Clear (); // Limpa todo o documento
Limpar (myDiv); // Limpa o painel referenciado por myDiv
fonte
O JavaScript é uma linguagem sem tipo e acho que faz sentido sobrecarregar um método / função com relação ao número de parâmetros. Portanto, eu recomendaria verificar se o parâmetro foi definido:
fonte
Em julho de 2017, a seguinte técnica era comum. Observe que também podemos executar a verificação de tipo dentro da função.
fonte
Para o seu caso de uso, é assim que eu o abordaria
ES6
(já que já é o final de 2017):Obviamente, você pode adaptar isso para trabalhar com qualquer quantidade de parâmetros e apenas alterar suas instruções condicionais de acordo.
fonte
não há sobrecarga real no JS, de qualquer forma, ainda podemos simular a sobrecarga do método de várias maneiras:
método # 1: usar objeto
método # 2: use os parâmetros rest (spread)
método # 3: use indefinido
método # 4: verificação de tipo
fonte
Embora os parâmetros padrão não estejam sobrecarregando, eles podem resolver alguns dos problemas enfrentados pelos desenvolvedores nesta área. A entrada é estritamente decidida pelo pedido, não é possível reordenar como desejar, como na sobrecarga clássica:
Resultados em (para o ano 2020):
Mais informações: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters
fonte
A primeira opção realmente merece atenção porque é o que eu vim em uma configuração de código bastante complexa. Então, minha resposta é
Com uma pequena dica, porém essencial, os nomes devem parecer diferentes para o computador, mas não para você. Nomeie funções sobrecarregadas como: func, func1, func2.
fonte