Acho que o recurso de parâmetros nomeados em C # é bastante útil em alguns casos.
calculateBMI(70, height: 175);
O que posso usar se eu quiser isso em JavaScript?
O que eu não quero é isso:
myFunction({ param1: 70, param2: 175 });
function myFunction(params){
// Check if params is an object
// Check if the parameters I need are non-null
// Blah blah
}
Essa abordagem eu já usei. Existe outro caminho?
Estou bem usando qualquer biblioteca para fazer isso.
javascript
function
optional-parameters
named-parameters
Robin Maben
fonte
fonte
Function
em javascript pode fazer.Function
em Javascript não pode alterar a sintaxe principal do JavascriptcalculateBMI(70, /*height:*/ 175);
, (2) fornecer um objetocalculateBMI(70, {height: 175})
ou (3) usar uma constanteconst height = 175; calculateBMI(70, height);
.Respostas:
ES2015 e posterior
No ES2015, a destruição de parâmetros pode ser usada para simular parâmetros nomeados. Exigiria que o chamador passasse um objeto, mas você pode evitar todas as verificações dentro da função se também usar parâmetros padrão:
ES5
Existe uma maneira de chegar perto do que você deseja, mas é baseado na saída do
Function.prototype.toString
[ES5] , que depende da implementação em algum grau, portanto pode não ser compatível com vários navegadores.A ideia é analisar os nomes dos parâmetros a partir da representação em cadeia da função, para que você possa associar as propriedades de um objeto ao parâmetro correspondente.
Uma chamada de função pode parecer
onde
a
eb
são argumentos posicionais e o último argumento é um objeto com argumentos nomeados.Por exemplo:
Que você usaria como:
DEMO
Existem algumas desvantagens nessa abordagem (você foi avisado!):
undefined
(isso é diferente de não ter nenhum valor). Isso significa que você não pode usararguments.length
para testar quantos argumentos foram passados.Em vez de ter uma função criando o wrapper, você também pode ter uma função que aceite uma função e vários valores como argumentos, como
ou até estender
Function.prototype
para que você possa fazer:fonte
Object.defineProperty
e definirenumerable
comofalse
). Deve-se sempre ter cuidado ao estender objetos nativos. Toda a abordagem sente um hacky pouco, então eu não esperaria que ele funcione agora e para sempre;)undefined
vs "sem valor", pode-se acrescentar que é exatamente assim que os valores padrão das funções JS estão funcionando - tratandoundefined
como um valor ausente.Não - a abordagem de objetos é a resposta do JavaScript para isso. Não há problema com isso, desde que sua função espere um objeto em vez de parâmetros separados.
fonte
Esse problema tem sido um problema para mim há algum tempo. Sou um programador experiente, com muitas línguas em meu currículo. Um dos meus idiomas favoritos que tive o prazer de usar é o Python. O Python suporta parâmetros nomeados sem nenhum truque .... Desde que comecei a usar o Python (há algum tempo) tudo ficou mais fácil. Acredito que todo idioma deve suportar parâmetros nomeados, mas esse não é o caso.
Muitas pessoas dizem apenas usar o truque "Passar um objeto" para que você tenha nomeado parâmetros.
E isso funciona muito bem, exceto ... quando se trata da maioria dos IDEs existentes, muitos de nós desenvolvedores dependemos de dicas de tipo / argumento em nosso IDE. Eu pessoalmente uso o PHP Storm (junto com outros IDEs do JetBrains, como PyCharm para python e AppCode para Objective C)
E o maior problema ao usar o truque "Passar um objeto" é que, quando você está chamando a função, o IDE fornece uma dica de tipo único e é isso ... Como devemos saber quais parâmetros e tipos devem ser inseridos no objeto arg1?
Então ... o truque "Passar um objeto" não funciona para mim ... Na verdade, causa mais dores de cabeça ao analisar o docblock de cada função antes que eu saiba quais parâmetros a função espera ... Claro, é ótimo para quando você está mantendo o código existente, mas é horrível escrever um novo código.
Bem, esta é a técnica que eu uso ... Agora, pode haver alguns problemas com ela, e alguns desenvolvedores podem me dizer que estou fazendo errado, e eu tenho uma mente aberta quando se trata dessas coisas ... Estou sempre disposto a procurar maneiras melhores de realizar uma tarefa ... Portanto, se houver um problema com essa técnica, os comentários serão bem-vindos.
Dessa forma, eu tenho o melhor dos dois mundos ... é fácil escrever um novo código, pois meu IDE me fornece todas as sugestões de argumentos adequadas ... E, mantendo o código posteriormente, posso ver de relance, não apenas o valor passado para a função, mas também o nome do argumento. A única sobrecarga que vejo é declarar os nomes dos seus argumentos como variáveis locais para não poluir o espaço para nome global. Claro, é um pouco de digitação extra, mas trivial em comparação com o tempo necessário para procurar blocos de documentos enquanto escrevia um novo código ou mantinha o código existente.
fonte
myFunc(/*arg1*/ 'Param1', /*arg2*/ 'Param2');
é melhor do quemyFunc(arg1='Param1', arg2='Param2');
, porque isso não tem nenhuma chance de enganar o leitor do que qualquer reais argumentos nomeados estão acontecendoSe você quiser deixar claro quais são os parâmetros, em vez de apenas chamar
por que não fazer o seguinte
com certeza, é uma linha extra de código, mas vence na legibilidade.
fonte
someFunction(height: 115);
mas se você escrever,someFunction(height);
estará definindo a largura.someFunction(width = 70, height = 115);
. As variáveis são declaradas no topo do escopo atual no código JavaScript gerado.Outra maneira seria usar atributos de um objeto adequado, por exemplo:
Obviamente, para este exemplo inventado, é um tanto sem sentido. Mas nos casos em que a função se parece
pode ser mais útil. Também poderia ser combinado com a idéia "parameterfy" para criar esse objeto a partir de uma função existente de uma maneira genérica. Isto é, para cada parâmetro, ele criaria um membro que pode ser avaliado como uma versão avaliada parcial da função.
Obviamente, essa ideia está relacionada ao Schönfinkeling, também conhecido como Currying.
fonte
Existe outro caminho. Se você estiver passando um objeto por referência, as propriedades desse objeto aparecerão no escopo local da função. Sei que isso funciona para o Safari (não verifiquei outros navegadores) e não sei se esse recurso tem um nome, mas o exemplo abaixo ilustra seu uso.
Embora na prática eu não pense que isso ofereça algum valor funcional além da técnica que você já está usando, é um pouco mais limpo semanticamente. E ainda requer a passagem de uma referência de objeto ou de um literal de objeto.
fonte
Tentando o Nó-6.4.0 (process.versions.v8 = '5.0.71.60') e o Nó Chakracore-v7.0.0-pre8 e depois o Chrome-52 (V8 = 5.2.361.49), notei que os parâmetros nomeados são quase implementado, mas essa ordem ainda tem precedência. Não consigo encontrar o que diz o padrão ECMA.
Mas a ordem é necessária !! É o comportamento padrão?
fonte
b=10
expressão é10
, e é isso que é passado para a função.f(bla=10)
também funcionaria (atribui 10 à variávelbla
e passa o valor para a função posteriormente).a
eb
variáveis no escopo global como efeito colateral.Função de chamada
f
com parâmetros nomeados passados como o objetoestá basicamente chamando sua composição
f(...g(o))
onde estou usando a sintaxe de propagação eg
é um mapa de "ligação" que conecta os valores do objeto com suas posições de parâmetro.O mapa de ligação é precisamente o ingrediente que falta, que pode ser representado pela matriz de suas chaves:
Observe os três ingredientes dissociados: a função, o objeto com argumentos nomeados e a ligação. Esse desacoplamento permite muita flexibilidade para usar essa construção, em que a ligação pode ser arbitrariamente personalizada na definição da função e arbitrariamente estendida no momento da chamada da função.
Por exemplo, você pode querer para abreviar
height
ewidth
comoh
ew
dentro de definição da sua função, para torná-lo mais curto e mais limpa, enquanto você ainda quiser chamá-lo com nomes completos para maior clareza:Essa flexibilidade também é mais útil para programação funcional, onde as funções podem ser arbitrariamente transformadas, perdendo seus nomes de parâmetros originais.
fonte
Vindo de Python, isso me incomodou. Eu escrevi um wrapper / proxy simples para o nó que aceitará objetos posicionais e de palavras-chave.
https://github.com/vinces1979/node-def/blob/master/README.md
fonte
f(x, opt)
ondeopt
está um objeto. Se isso ajuda a evitar ou a criar erros (como erros ortográficos e problemas para lembrar nomes de palavras-chave) permanece uma questão.kwargs
ditado uma a uma e, por fim, gera umTypeError
se as chaves desconhecidas forem deixadas). Suaf(x, opt)
solução permite que af
função faça algo como no Python 2, mas você precisaria lidar com todos os valores padrão.f(x, opt)
já está funcionando, enquanto não vejo como isso ajuda a responder à pergunta, onde, por exemplo, você deseja fazer as duas coisasrequest(url)
erequest({url: url})
isso não seria possível criandourl
um parâmetro apenas de palavra-chave.Ao contrário do que geralmente se acredita, os parâmetros nomeados podem ser implementados no JavaScript padrão da velha escola (apenas para parâmetros booleanos) por meio de uma convenção de codificação simples e clara, como mostrado abaixo.
Ressalvas:
A ordem dos argumentos deve ser preservada - mas o padrão ainda é útil, pois torna óbvio qual argumento real se destina a qual parâmetro formal, sem a necessidade de grep para a assinatura da função ou usar um IDE.
Isso funciona apenas para booleanos. No entanto, tenho certeza de que um padrão semelhante poderia ser desenvolvido para outros tipos usando a semântica de coerção de tipo exclusivo do JavaScript.
fonte
height
pelo nome, independentemente da ordem dos parâmetros.