Abordagem clássica (não js) para sobrecarregar:
function myFunc(){
//code
}
function myFunc(overloaded){
//other code
}
Javascript não permite que mais de uma função seja definida com o mesmo nome. Como tal, coisas como esta aparecem:
function myFunc(options){
if(options["overloaded"]){
//code
}
}
Existe uma solução melhor para sobrecarga de função em javascript do que passar um objeto com as sobrecargas nele?
Transmitir sobrecargas pode rapidamente fazer com que uma função se torne muito detalhada, pois cada sobrecarga possível precisaria de uma instrução condicional. Usar funções para realizar o //code
interior dessas instruções condicionais pode causar situações complicadas com escopos.
javascript
Travis J
fonte
fonte
Respostas:
Existem vários aspectos para sobrecarga de argumento em Javascript:
Argumentos variáveis - você pode passar diferentes conjuntos de argumentos (em tipo e quantidade) e a função se comportará de uma maneira que corresponda aos argumentos passados a ela.
Argumentos padrão - você pode definir um valor padrão para um argumento se ele não for passado.
Argumentos nomeados - a ordem dos argumentos torna-se irrelevante e você apenas nomeia quais argumentos deseja passar para a função.
Abaixo está uma seção sobre cada uma dessas categorias de tratamento de argumentos.
Argumentos Variáveis
Como o javascript não tem verificação de tipo em argumentos ou quantidade necessária de argumentos, você pode ter apenas uma implementação
myFunc()
que pode se adaptar aos argumentos que foram passados a ele verificando o tipo, presença ou quantidade de argumentos.jQuery faz isso o tempo todo. Você pode tornar alguns dos argumentos opcionais ou pode ramificar em sua função, dependendo de quais argumentos são passados para ela.
Ao implementar esses tipos de sobrecargas, você tem várias técnicas diferentes que pode usar:
undefined
.arguments.length
.arguments
pseudo-matriz para acessar qualquer argumento comarguments[i]
.aqui estão alguns exemplos:
Vejamos o
obj.data()
método jQuery . Ele suporta quatro formas diferentes de uso:Cada um aciona um comportamento diferente e, sem usar essa forma dinâmica de sobrecarga, exigiria quatro funções distintas.
Veja como se pode discernir entre todas essas opções em inglês e, em seguida, combinarei todas no código:
Se o primeiro argumento passado para
.data()
for uma string e o segundo argumento forundefined
, então o chamador deve usar este formulário.Se o segundo argumento não for indefinido, defina o valor de uma chave específica.
Se nenhum argumento for passado, retorne todas as chaves / valores em um objeto retornado.
Se o tipo do primeiro argumento for um objeto simples, defina todas as chaves / valores desse objeto.
Veja como você pode combinar tudo isso em um conjunto de lógica javascript:
A chave para essa técnica é certificar-se de que todas as formas de argumentos que você deseja aceitar sejam identificáveis de forma única e que nunca haja confusão sobre qual formulário o chamador está usando. Isso geralmente requer ordenar os argumentos de forma adequada e certificar-se de que haja exclusividade suficiente no tipo e na posição dos argumentos para que você sempre possa saber qual forma está sendo usada.
Por exemplo, se você tem uma função que recebe três argumentos de string:
Você pode facilmente tornar o terceiro argumento opcional e detectar facilmente essa condição, mas você não pode tornar apenas o segundo argumento opcional porque você não pode dizer qual deles o chamador pretende passar porque não há como identificar se o segundo argumento deve ser o segundo argumento ou o segundo argumento foi omitido, então o que está no lugar do segundo argumento é na verdade o terceiro argumento:
Como todos os três argumentos são do mesmo tipo, você não pode dizer a diferença entre os diferentes argumentos, portanto não sabe o que o chamador pretendia. Com este estilo de chamada, apenas o terceiro argumento pode ser opcional. Se você quisesse omitir o segundo argumento, ele teria que ser passado como
null
(ou algum outro valor detectável) e seu código detectaria que:Aqui está um exemplo jQuery de argumentos opcionais. ambos os argumentos são opcionais e assumem os valores padrão se não forem passados:
Aqui está um exemplo de jQuery em que o argumento pode estar ausente ou qualquer um dos três tipos diferentes que fornecem quatro sobrecargas diferentes:
Argumentos Nomeados
Outras linguagens (como Python) permitem que se passe argumentos nomeados como um meio de passar apenas alguns argumentos e tornar os argumentos independentes da ordem em que são passados. Javascript não suporta diretamente o recurso de argumentos nomeados. Um padrão de design comumente usado em seu lugar é passar um mapa de propriedades / valores. Isso pode ser feito passando um objeto com propriedades e valores ou no ES6 e acima, você pode realmente passar um objeto Mapa em si.
Aqui está um exemplo ES5 simples:
jQuery's
$.ajax()
aceita uma forma de uso em que você apenas passa um único parâmetro que é um objeto Javascript regular com propriedades e valores. Quais propriedades você passa determinam quais argumentos / opções estão sendo passados para a chamada ajax. Alguns podem ser obrigatórios, muitos são opcionais. Como são propriedades de um objeto, não existe uma ordem específica. Na verdade, existem mais de 30 propriedades diferentes que podem ser passadas para aquele objeto, apenas uma (o url) é necessária.Aqui está um exemplo:
Dentro da
$.ajax()
implementação, ele pode apenas interrogar quais propriedades foram passadas no objeto de entrada e usá-las como argumentos nomeados. Isso pode ser feito comfor (prop in obj)
ou obtendo todas as propriedades em uma matrizObject.keys(obj)
e, em seguida, iterando essa matriz.Esta técnica é usada muito comumente em Javascript quando há um grande número de argumentos e / ou muitos argumentos são opcionais. Observação: isso coloca um ônus sobre a função de implementação para garantir que um conjunto mínimo válido de argumentos esteja presente e dar ao chamador algum feedback de depuração o que está faltando se argumentos insuficientes forem passados (provavelmente lançando uma exceção com uma mensagem de erro útil) .
Em um ambiente ES6, é possível usar a desestruturação para criar propriedades / valores padrão para o objeto passado acima. Isso é discutido com mais detalhes neste artigo de referência .
Aqui está um exemplo desse artigo:
Isto cria propriedades padrão e os valores para a
start
,end
estep
as propriedades de um objecto transmitido para aselectEntries()
função.Valores padrão para argumentos de função
No ES6, o Javascript adiciona suporte de idioma integrado para valores padrão de argumentos.
Por exemplo:
Uma descrição mais detalhada das maneiras como isso pode ser usado aqui no MDN .
fonte
resetProgressBar: function(display_errors, lockout = false)
.Sobrecarregar uma função em JavaScript pode ser feito de várias maneiras. Todos eles envolvem uma única função mestre que executa todos os processos ou delega a subfunções / processos.
Uma das técnicas simples mais comuns envolve uma troca simples:
Uma técnica mais elegante seria usar uma matriz (ou objeto, se você não estiver fazendo sobrecargas para cada contagem de argumento):
O exemplo anterior não é muito elegante, qualquer pessoa pode modificar
fooArr
e falhará se alguém passar mais de 2 argumentos parafoo
, então uma forma melhor seria usar um padrão de módulo e algumas verificações:Claro que suas sobrecargas podem querer usar um número dinâmico de parâmetros, então você pode usar um objeto para a
fns
coleção.Minha preferência pessoal tende a ser
switch
, embora aumente a função mestre. Um exemplo comum de onde eu usaria essa técnica seria um método acessador / modificador:fonte
Você não pode sobrecarregar o método em sentido estrito. Não gosto da forma como é suportado em
java
ouc#
.O problema é que o JavaScript NÃO oferece suporte nativo à sobrecarga de método. Portanto, se ele vir / analisar duas ou mais funções com os mesmos nomes, ele apenas considerará a última função definida e sobrescreverá as anteriores.
Uma das maneiras que considero adequada para a maioria dos casos é a seguinte -
Vamos dizer que você tem método
Em vez de sobrecarregar o método, o que não é possível em javascript, você pode definir um novo método
e, em seguida, modifique a 1ª função da seguinte forma -
Se você tiver muitos desses métodos sobrecarregados, considere usar
switch
não apenasif-else
instruções.( mais detalhes ) PS: O link acima leva ao meu blog pessoal que tem detalhes adicionais sobre isso.
fonte
Estou usando uma abordagem de sobrecarga um pouco diferente com base no número de argumentos. No entanto, acredito que a abordagem de John Fawcett também é boa. Aqui está o exemplo, código baseado nas explicações de John Resig (autor do jQuery).
usabilidade:
fonte
Em javascript você pode implementar a função apenas uma vez e invocar a função sem os parâmetros
myFunc()
Você então verifica se as opções estão 'indefinidas'fonte
Tentei desenvolver uma solução elegante para este problema descrito aqui . E você pode encontrar a demonstração aqui . O uso é parecido com este:
Os métodos usados para conseguir isso:
fonte
https://github.com/jrf0110/leFunc
fonte
Nenhum problema com sobrecarga em JS, O pb como manter um código limpo ao sobrecarregar a função?
Você pode usar um encaminhamento para ter um código limpo, com base em duas coisas:
Tipo de argumento (ao chamar a função)
fonte
Veja isso:
http://www.codeproject.com/Articles/688869/Overloading-JavaScript-Functions
Basicamente, em sua classe, você numera as funções que deseja sobrecarregar e, em seguida, com uma chamada de função, adiciona a sobrecarga de função, de forma rápida e fácil.
fonte
Como o JavaScript não tem opções de sobrecarga de função , o objeto pode ser usado. Se houver um ou dois argumentos necessá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
Para isso, você precisa criar uma função que adiciona a função a um objeto, então ela será executada dependendo da quantidade de argumentos que você enviar para a função:
fonte
Gosto de adicionar subfunções dentro de uma função pai para conseguir a capacidade de diferenciar grupos de argumentos para a mesma funcionalidade.
fonte
O que você está tentando alcançar é melhor feito usando a variável de argumentos locais da função .
Você pode encontrar uma explicação melhor de como isso funciona aqui .
fonte