Ao criar uma função JavaScript com vários argumentos, sempre sou confrontado com esta opção: passe uma lista de argumentos versus passe um objeto de opções.
Por exemplo, estou escrevendo uma função para mapear um nodeList para uma matriz:
function map(nodeList, callback, thisObject, fromIndex, toIndex){
...
}
Eu poderia usar isso:
function map(options){
...
}
onde options é um objeto:
options={
nodeList:...,
callback:...,
thisObject:...,
fromIndex:...,
toIndex:...
}
Qual é o caminho recomendado? Existem diretrizes para quando usar um vs. o outro?
[Update] Parece haver um consenso a favor do objeto de opções, então eu gostaria de adicionar um comentário: uma razão pela qual fiquei tentada a usar a lista de argumentos no meu caso foi ter um comportamento consistente com o JavaScript incorporado no método array.map.
Array.prototype.map
tem uma API simples que não deve deixar nenhum codificador semi-experiente intrigado.Respostas:
Como muitos outros, geralmente prefiro passar um
options object
para uma função em vez de passar uma longa lista de parâmetros, mas isso realmente depende do contexto exato.Eu uso a legibilidade do código como teste decisivo.
Por exemplo, se eu tiver essa chamada de função:
Eu acho que o código é bem legível do jeito que é e passar parâmetros individuais é bom.
Por outro lado, existem funções com chamadas como esta:
Completamente ilegível, a menos que você faça alguma pesquisa. Por outro lado, esse código lê bem:
É mais uma arte do que uma ciência, mas se eu tivesse que citar regras práticas:
Use um parâmetro de opções se:
fonte
Vários argumentos são principalmente para parâmetros obrigatórios. Não há nada de errado com eles.
Se você possui parâmetros opcionais, fica complicado. Se um deles depende dos outros, para que eles tenham uma certa ordem (por exemplo, a quarta precisa da terceira), você ainda deve usar vários argumentos. Quase todos os métodos nativos de EcmaScript e DOM funcionam assim. Um bom exemplo é o
open
método XMLHTTPrequests , em que os três últimos argumentos são opcionais - a regra é como "sem senha sem usuário" (consulte também os documentos MDN ).Os objetos Option são úteis em dois casos:
undefined
.No seu caso, eu recomendo
map(nodeList, callback, options)
.nodelist
ecallback
são obrigatórios, os outros três argumentos são apresentados apenas ocasionalmente e têm padrões razoáveis.Outro exemplo é
JSON.stringify
. Você pode querer usar ospace
parâmetro sem passar umareplacer
função - então você precisa chamar…, null, 4)
. Um objeto de argumentos pode ter sido melhor, embora não seja realmente razoável para apenas 2 parâmetros.fonte
Usar a abordagem 'opções como objeto' será o melhor. Você não precisa se preocupar com a ordem das propriedades e há mais flexibilidade em quais dados são passados (parâmetros opcionais, por exemplo)
Criar um objeto também significa que as opções podem ser usadas facilmente em várias funções:
fonte
Eu acho que se você está instanciando algo ou chamando o método de um objeto, deseja usar um objeto de opções. Se é uma função que opera com apenas um ou dois parâmetros e retorna um valor, uma lista de argumentos é preferível.
Em alguns casos, é bom usar os dois. Se sua função tiver um ou dois parâmetros necessários e vários opcionais, torne os dois primeiros parâmetros necessários e o terceiro um hash de opções opcionais.
No seu exemplo, eu faria
map(nodeList, callback, options)
. Nodelist e retorno de chamada são necessários, é bastante fácil dizer o que está acontecendo apenas lendo uma chamada e é como as funções existentes do mapa. Quaisquer outras opções podem ser passadas como um terceiro parâmetro opcional.fonte
O seu comentário sobre a pergunta:
Então, por que não fazer isso? (Nota: Este é um Javascript bastante bruto. Normalmente, eu usaria um
default
hash e o atualizaria com as opções passadas usando Object.extend ou JQuery.extend ou similar ..)Então, agora que agora é muito mais óbvio o que é opcional e o que não é, todos esses são usos válidos da função:
fonte
Posso estar um pouco atrasado para a festa com essa resposta, mas estava procurando as opiniões de outros desenvolvedores sobre esse mesmo tópico e me deparei com esse tópico.
Eu discordo muito da maioria dos respondentes e sou do lado da abordagem de 'múltiplos argumentos'. Meu argumento principal é que desencoraja outros antipadrões como "mutação e retorno do objeto param" ou "transmissão do mesmo objeto param para outras funções". Eu trabalhei em bases de código que abusaram extensivamente desse anti-padrão e o código de depuração que faz isso rapidamente se torna impossível. Eu acho que essa é uma regra prática muito específica para Javascript, pois o Javascript não é fortemente digitado e permite esses objetos estruturados arbitrariamente.
Minha opinião pessoal é que os desenvolvedores devem ser explícitos ao chamar funções, evitar a transmissão de dados redundantes e evitar a modificação por referência. Não é que esse padrão impeça a criação de um código conciso e correto. Eu apenas sinto que torna muito mais fácil o seu projeto cair em más práticas de desenvolvimento.
Considere o seguinte código terrível:
Esse tipo de documentação não apenas exige uma documentação mais explícita para especificar a intenção, como também deixa espaço para erros vagos. O que se um desenvolvedor modifica
param1
embar()
? Quanto tempo você acha que seria necessário analisar uma base de código de tamanho suficiente para capturar isso? É certo que este exemplo é um pouco falso, pois supõe que os desenvolvedores já tenham cometido vários antipadrões nesse ponto. Mas mostra como a passagem de objetos contendo parâmetros permite maior espaço para erro e ambiguidade, exigindo um maior grau de consciência e observância da correção constante.Apenas meus dois centavos na questão!
fonte
Depende.
Com base na minha observação sobre o design de bibliotecas populares, aqui estão os cenários que devemos usar o objeto de opção:
E cenários para usar a lista de parâmetros:
fonte
O objeto é mais preferível, porque se você passa um objeto, é fácil estender o número de propriedades nesses objetos e não precisa observar a ordem na qual seus argumentos foram passados.
fonte
Para uma função que geralmente usa alguns argumentos predefinidos, é melhor usar o objeto de opção. O exemplo oposto será algo como uma função que está obtendo um número infinito de argumentos como: setCSS ({height: 100}, {width: 200}, {background: "# 000"}).
fonte
Gostaria de olhar para grandes projetos javascript.
Coisas como o google map, você verá com frequência que objetos instanciados requerem um objeto, mas funções requerem parâmetros. Eu acho que isso tem a ver com argumentos de OPÇÃO.
Se você precisar de argumentos padrão ou opcionais, um objeto provavelmente seria melhor porque é mais flexível. Mas se você não usar argumentos funcionais normais, será mais explícito.
Javascript também tem um
arguments
objeto. https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Functions_and_function_scope/argumentsfonte