Eu já vi dois métodos para determinar se um argumento foi passado para uma função JavaScript. Gostaria de saber se um método é melhor que o outro ou se é apenas ruim de usar?
function Test(argument1, argument2) {
if (Test.arguments.length == 1) argument2 = 'blah';
alert(argument2);
}
Test('test');
Ou
function Test(argument1, argument2) {
argument2 = argument2 || 'blah';
alert(argument2);
}
Test('test');
Tanto quanto posso dizer, ambos resultam na mesma coisa, mas eu só usei o primeiro antes na produção.
Outra opção, como mencionado por Tom :
function Test(argument1, argument2) {
if(argument2 === null) {
argument2 = 'blah';
}
alert(argument2);
}
Conforme o comentário de Juan, seria melhor mudar a sugestão de Tom para:
function Test(argument1, argument2) {
if(argument2 === undefined) {
argument2 = 'blah';
}
alert(argument2);
}
javascript
arguments
Darryl Hein
fonte
fonte
argument2 || 'blah';
resultará em 'blá' seargument2
forfalse
(!), Não simplesmente se for indefinido. Seargument2
for um booleano e a função for passadafalse
para ele, essa linha retornará 'blá', apesar deargument2
ser definida corretamente .argument2
é0
,''
ounull
.Respostas:
Existem várias maneiras diferentes de verificar se um argumento foi passado para uma função. Além das duas que você mencionou na sua pergunta (original) - verificando
arguments.length
ou usando o||
operador para fornecer valores padrão - também é possível verificar explicitamente os argumentos porundefined
viaargument2 === undefined
outypeof argument2 === 'undefined'
se é paranóico (consulte os comentários).Usando o
||
operador tornou-se prática padrão - todos os miúdos legal fazê-lo - mas tenha cuidado: o valor padrão será acionado se os avalia argumento parafalse
, o que significa que pode realmente serundefined
,null
,false
,0
,''
(ou qualquer outra coisa para a qualBoolean(...)
retornafalse
).Portanto, a questão é quando usar essa verificação, pois todas elas produzem resultados ligeiramente diferentes.
A verificação
arguments.length
exibe o comportamento 'mais correto', mas pode não ser possível se houver mais de um argumento opcional.O teste para
undefined
é o próximo 'melhor' - apenas 'falha' se a função for chamada explicitamente com umundefined
valor, que provavelmente deve ser tratado da mesma maneira que omitir o argumento.O uso do
||
operador pode acionar o uso do valor padrão, mesmo que um argumento válido seja fornecido. Por outro lado, seu comportamento pode realmente ser desejado.Para resumir: use-o apenas se você souber o que está fazendo!
Na minha opinião, usar
||
também é o caminho a percorrer se houver mais de um argumento opcional e não se desejar passar um literal de objeto como uma solução alternativa para os parâmetros nomeados.Outra boa maneira de fornecer valores padrão
arguments.length
é possível através dos rótulos de uma instrução switch:Isso tem o lado negativo de que a intenção do programador não é (visualmente) óbvia e usa 'números mágicos'; é, portanto, possivelmente propenso a erros.
fonte
Se você estiver usando o jQuery, uma opção interessante (especialmente para situações complicadas) é usar o método de extensão do jQuery .
Se você chamar a função, faça o seguinte:
A variável options seria então:
fonte
Este é um dos poucos casos em que encontro o teste:
funciona muito bem e carrega a implicação correta sintaticamente.
(Com a restrição simultânea de que eu não permitiria um valor nulo legítimo para o
argument2
qual tenha algum outro significado; mas isso seria realmente confuso.)EDITAR:
Este é realmente um bom exemplo de diferença estilística entre linguagens de tipo fraco e forte; e uma opção estilística que o javascript oferece em espadas.
Minha preferência pessoal (sem críticas para outras preferências) é minimalismo. Quanto menos o código tiver a dizer, desde que eu seja consistente e conciso, menos alguém precisará compreender para inferir corretamente meu significado.
Uma implicação dessa preferência é que eu não quero - não acho útil - acumular vários testes de dependência de tipo. Em vez disso, tento fazer com que o código signifique o que parece; e teste apenas o que realmente preciso testar.
Um dos agravos que encontro no código de outras pessoas está precisando descobrir se eles esperam ou não, em um contexto mais amplo, realmente encontrar os casos pelos quais estão testando. Ou se eles estão tentando testar o máximo possível, com a chance de não antecipar o contexto completamente o suficiente. O que significa que acabo precisando rastreá-los exaustivamente nas duas direções antes de poder refatorar ou modificar qualquer coisa com confiança. Acho que há uma boa chance de que eles possam ter implementado esses vários testes porque previram circunstâncias onde seriam necessárias (e que geralmente não são aparentes para mim).
(Considero isso uma desvantagem séria na maneira como essas pessoas usam linguagens dinâmicas. Muitas vezes as pessoas não querem desistir de todos os testes estáticos e acabam fingindo.)
Eu já vi isso de maneira flagrante ao comparar o código abrangente do ActionScript 3 com o elegante código javascript. O AS3 pode ser 3 ou 4 vezes a maior parte dos js, e a confiabilidade que eu suspeito é pelo menos não melhor, apenas por causa do número (3-4X) de decisões de codificação que foram tomadas.
Como você diz, Shog9, YMMV. : D
fonte
Existem diferenças significativas. Vamos configurar alguns casos de teste:
Com o primeiro método que você descreve, apenas o segundo teste usa o valor padrão. O segundo método será o padrão todos, mas o primeiro (como JS irá converter
undefined
,null
,0
, e""
para o booleanfalse
. E se você fosse usar o método de Tom, apenas o quarto teste usará o padrão!O método escolhido depende realmente do comportamento pretendido. Se outros valores
undefined
são permitidosargument2
, provavelmente você desejará alguma variação no primeiro; se um valor diferente de zero, nulo e não vazio é desejado, o segundo método é ideal - na verdade, ele é frequentemente usado para eliminar rapidamente uma ampla variedade de valores da consideração.fonte
fonte
No ES6 (ES2015), você pode usar Parâmetros padrão
fonte
"default value"
e verificando se o valor é realmente"default value"
.Sinto muito, ainda não posso comentar, então, para responder à resposta de Tom ... Em javascript (indefinido! = Null) == false Na verdade, essa função não funcionará com "null", você deve usar "undefined"
fonte
Por que não usar o
!!
operador? Esse operador, colocado antes da variável, transforma-o em um booleano (se eu entendi bem), então!!undefined
e!!null
(e até!!NaN
, o que pode ser bem interessante) retornaráfalse
.Aqui está um exemplo:
fonte
Pode ser conveniente abordar a detecção de argumentos, evocando sua função com um Objeto de propriedades opcionais:
fonte
Também há uma maneira complicada de descobrir se um parâmetro é passado para uma função ou não . Veja o exemplo abaixo:
Isso necessário significa que, se o valor de
value
não estiver presente / passado - defina-o como 0.Muito legal né!
fonte
value
for equivalente afalse
, defina-o como 0." Essa é uma distinção sutil, mas muito importante.true
efalse
forem valores válidos, convém ter um terceiro comportamento para quando o parâmetro não for passado (especialmente se a função tiver mais de um parâmetro).Algumas vezes você também pode querer verificar o tipo, especialmente se estiver usando a função como getter e setter. O código a seguir é ES6 (não será executado no EcmaScript 5 ou mais antigo):
fonte
Porque matrizes são herdadas de
Object.prototype
. Considere ⇑ para tornar o mundo melhor.fonte
fnCalledFunction (Param1, Param2, window.YourOptionalParameter)
Se a função acima for chamada de muitos lugares e você tiver certeza de que os 2 primeiros parâmetros foram passados de todos os locais, mas não tiver certeza do terceiro parâmetro, poderá usar a janela.
window.param3 tratará se não for definido no método de chamada.
fonte