Existe uma maneira melhor para fazer os parâmetros de função opcionais em JavaScript? [duplicado]

StackOverflow https://stackoverflow.com/questions/148901

  •  02-07-2019
  •  | 
  •  

Pergunta

Esta questão já tem uma resposta aqui:

Eu sempre tratado parâmetros opcionais em JavaScript como este:

function myFunc(requiredArg, optionalArg){
  optionalArg = optionalArg || 'defaultValue';

  // Do stuff
}

Existe uma maneira melhor de fazer isso?

Existem casos onde o uso || assim vai falhar?

Foi útil?

Solução

Sua lógica falha se optionalArg é passado, mas avalia como falso - tentar isso como uma alternativa

if (typeof optionalArg === 'undefined') { optionalArg = 'default'; }

Ou uma linguagem alternativa:

optionalArg = (typeof optionalArg === 'undefined') ? 'default' : optionalArg;

Use o que idioma se comunica a melhor intenção de você!

Outras dicas

Em ECMAScript 2015 (aka "ES6") você pode declarar valores de argumento padrão na declaração da função:

function myFunc(requiredArg, optionalArg = 'defaultValue') {
    // do stuff
}

Mais sobre eles em este artigo em MDN .

Este é atualmente suportado apenas pelo Firefox , mas como o padrão tenha sido concluído, esperar o apoio para melhorar rapidamente.

EDIT (2019/06/12):

Os parâmetros predefinidos são agora amplamente suportado pelos navegadores modernos. Todas as versões do Internet Explorer não suportam esta funcionalidade. No entanto, Chrome, Firefox, e Edge atualmente apoiá-lo.

Eu acho que esta é a maneira mais simples, mais legível:

if (typeof myVariable === 'undefined') { myVariable = 'default'; }
//use myVariable here

A resposta de Paul Dixon (na minha humilde opinião) é menos legível do que isso, mas se resume a preferência.

A resposta de insin é muito mais avançado, mas muito mais útil para grandes funções!

EDIT 2013/11/17 09:33: Eu criei um pacote para Node.js que torna mais fácil a funções "sobrecarga" (métodos) chamados parametric .

Se você precisa atirar um NULL literal, então você pode ter alguns problemas. Para além de que, não, eu acho que você provavelmente está no caminho certo.

O outro método algumas pessoas optam está tomando uma série de variáveis ??assoc iteração através da lista de argumentos. Parece um pouco mais puro, mas eu imagino que é um pouco (muito pouco) pouco mais de processo / intensivo de memória.

function myFunction (argArray) {
    var defaults = {
        'arg1'  :   "value 1",
        'arg2'  :   "value 2",
        'arg3'  :   "value 3",
        'arg4'  :   "value 4"
    }

    for(var i in defaults) 
        if(typeof argArray[i] == "undefined") 
               argArray[i] = defaults[i];

    // ...
}

O ideal seria refatorar para passar um objeto e -lo com um objeto padrão, de modo a ordem em que os argumentos são passados ??não importa (ver a segunda seção desta resposta, abaixo).

Se, no entanto, você só quer algo rápido, confiável, fácil de usar e não volumoso, tente o seguinte:


Uma solução rápida limpa para qualquer número de argumentos padrão

  • É escalas elegantemente: código extra mínima para cada novo padrão
  • Você pode colá-lo em qualquer lugar: basta alterar o número de argumentos e variáveis ??necessárias
  • Se você quer passar undefined a um argumento com um valor padrão, desta forma, a variável é definida como undefined. A maioria das outras opções nesta página substituiria undefined com o valor padrão.

Aqui está um exemplo para fornecer padrões para três argumentos opcionais (com dois argumentos necessários)

function myFunc( requiredA, requiredB,  optionalA, optionalB, optionalC ) {

  switch (arguments.length - 2) { // 2 is the number of required arguments
    case 0:  optionalA = 'Some default';
    case 1:  optionalB = 'Another default';
    case 2:  optionalC = 'Some other default';
    // no breaks between cases: each case implies the next cases are also needed
  }

}

simples demonstração . Isto é semelhante ao resposta , mas facilmente extensível para qualquer número de argumentos padrão, mais fácil de atualizar e usando arguments não Function.arguments .


Passando e fundir objetos de maior flexibilidade

O código acima, como muitas maneiras de fazer argumentos padrão, não pode passar argumentos fora de seqüência, por exemplo, passando optionalC mas deixando optionalB a cair de volta ao seu padrão.

Uma boa opção para isso é para passar objetos e mesclar com um objeto padrão. Isso também é bom para a manutenção (apenas cuidar para manter seu legível código, para que futuros colaboradores não vai ficar na dúvida sobre os possíveis conteúdos dos objetos que você passar em torno).

Exemplo usando jQuery. Se você não usar o jQuery, você poderia passar a usar _.defaults(object, defaults) de Sublinhado ou browse estas opções :

function myFunc( args ) {
  var defaults = {
    optionalA: 'Some default',
    optionalB: 'Another default',
    optionalC: 'Some other default'
  };
  args = $.extend({}, defaults, args);
}

Aqui está um exemplo simples dele em ação .

Você pode usar alguns esquemas diferentes para isso. Eu sempre testados para arguments.length:

function myFunc(requiredArg, optionalArg){
  optionalArg = myFunc.arguments.length<2 ? 'defaultValue' : optionalArg;

  ...

- fazê-lo, não pode possivelmente falhar, mas eu não sei se o caminho tem alguma chance de falhar, só agora eu não posso pensar em um cenário, onde ele realmente iria falhar ...

E, em seguida, Paul fornecido um cenário não -!)

Semelhante a resposta de Oli, eu uso um objeto argumento e um objeto que define os valores padrão. Com um pouco de açúcar ...

/**
 * Updates an object's properties with other objects' properties. All
 * additional non-falsy arguments will have their properties copied to the
 * destination object, in the order given.
 */
function extend(dest) {
  for (var i = 1, l = arguments.length; i < l; i++) {
    var src = arguments[i]
    if (!src) {
      continue
    }
    for (var property in src) {
      if (src.hasOwnProperty(property)) {
        dest[property] = src[property]
      }
    }
  }
  return dest
}

/**
 * Inherit another function's prototype without invoking the function.
 */
function inherits(child, parent) {
  var F = function() {}
  F.prototype = parent.prototype
  child.prototype = new F()
  child.prototype.constructor = child
  return child
}

... isto pode ser feito um agradável pouco.

function Field(kwargs) {
  kwargs = extend({
    required: true, widget: null, label: null, initial: null,
    helpText: null, errorMessages: null
  }, kwargs)
  this.required = kwargs.required
  this.label = kwargs.label
  this.initial = kwargs.initial
  // ...and so on...
}

function CharField(kwargs) {
  kwargs = extend({
    maxLength: null, minLength: null
  }, kwargs)
  this.maxLength = kwargs.maxLength
  this.minLength = kwargs.minLength
  Field.call(this, kwargs)
}
inherits(CharField, Field)

O que há de bom sobre este método?

  • Você pode omitir tantos argumentos como você gosta - se só deseja para substituir o valor de um argumento, você pode apenas fornecer esse argumento, em vez de ter que passar explicitamente undefined quando, dizem que há 5 argumentos e só deseja para personalizar o último, como você teria a ver com alguns dos outros métodos sugeridos.
  • Ao trabalhar com uma função de construtor de um objeto que herda de outra, é fácil de aceitar quaisquer argumentos que são necessários pelo construtor do objeto que você está herdando de, como você não tem que nomear esses argumentos em sua assinatura de construtor, ou mesmo fornecer seus próprios padrões (deixar o construtor do objeto pai fazer isso por você, como visto acima, quando CharField chama o construtor de Field).
  • Criança objetos em hierarquias de herança pode personalizar argumentos para o seu construtor pai como entenderem, fazer valer os seus próprios valores padrão ou garantir que um determinado valor irá sempre ser utilizado.

Se você estiver usando padrões extensivamente, este parece muito mais legível:

function usageExemple(a,b,c,d){
    //defaults
    a=defaultValue(a,1);
    b=defaultValue(b,2);
    c=defaultValue(c,4);
    d=defaultValue(d,8);

    var x = a+b+c+d;
    return x;
}

Apenas declarar esta função no ESCOPE global.

function defaultValue(variable,defaultValue){
    return(typeof variable!=='undefined')?(variable):(defaultValue);
}

padrão de uso fruit = defaultValue(fruit,'Apple');

* PS você pode renomear a função defaultValue para um nome curto, só não use default é uma palavra reservada em JavaScript.

tipo solto verificação

fácil de escrever, mas 0, '', false, null e undefined será convertido para o valor padrão, que não pode ser esperado resultado.

function myFunc(requiredArg, optionalArg) {
    optionalArg = optionalArg || 'defaultValue';
}

tipo estrita verificação

mais tempo, mas as tampas maioria dos casos. Único caso em que ele incorretamente atribui valor padrão é quando passamos undefined como parâmetro.

function myFunc(requiredArg, optionalArg) {
    optionalArg = typeof optionalArg !== 'undefined' ? optionalArg : 'defaultValue';
}

Verificar argumentos variável

Pega todos os casos, mas é o mais desajeitado para escrita.

function myFunc(requiredArg, optionalArg1, optionalArg2) {
    optionalArg1 = arguments.length > 1 ? optionalArg1 : 'defaultValue';
    optionalArg2 = arguments.length > 2 ? optionalArg2 : 'defaultValue';
}

ES6

Infelizmente, este tem suporte ao navegador muito pobre no momento

function myFunc(requiredArg, optionalArg = 'defaultValue') {

}

Com ES2015 / ES6 você pode tirar vantagem de Object.assign que pode substituir $.extend() ou _.defaults()

function myFunc(requiredArg, options = {}) {
  const defaults = {
    message: 'Hello',
    color: 'red',
    importance: 1
  };

  const settings = Object.assign({}, defaults, options);

  // do stuff
}

Você também pode usar padrões argumentos como este

function myFunc(requiredArg, { message: 'Hello', color: 'red', importance: 1 } = {}) {
  // do stuff
}

Eu estou acostumado a ver algumas variações básicas sobre a manipulação variáveis ??opcionais. Às vezes, as versões relaxado são úteis.

function foo(a, b, c) {
  a = a || "default";   // Matches 0, "", null, undefined, NaN, false.
  a || (a = "default"); // Matches 0, "", null, undefined, NaN, false.

  if (b == null) { b = "default"; } // Matches null, undefined.

  if (typeof c === "undefined") { c = "default"; } // Matches undefined.
}

O padrão Falsas usado com a variável é, por exemplo, usado extensivamente em Backbone.js .

Se você estiver usando o href="http://underscorejs.org/#defaults" rel="nofollow"> Sublinhado biblioteca (você deve, que é uma biblioteca incrível):

_.defaults(optionalArg, 'defaultValue');

Landed a esta questão, em busca de parâmetros padrão em EcmaScript 2015 , portanto, apenas mencionar ...

Com ES6 podemos fazer default parâmetros :

function doSomething(optionalParam = "defaultValue"){
    console.log(optionalParam);//not required to check for falsy values
}

doSomething(); //"defaultValue"
doSomething("myvalue"); //"myvalue"

Durante um projeto que eu percebi que estava me repetir muito com os parâmetros e configurações opcionais, por isso fiz uma classe que manipula a verificação de tipo e atribui um valor padrão que resulta em código limpo e legível. Veja o exemplo e deixe-me saber se isso funciona para você.

var myCar           = new Car('VW', {gearbox:'automatic', options:['radio', 'airbags 2x']});
var myOtherCar      = new Car('Toyota');

function Car(brand, settings) {
    this.brand      = brand;

    // readable and adjustable code
    settings        = DefaultValue.object(settings, {});
    this.wheels     = DefaultValue.number(settings.wheels, 4);
    this.hasBreaks  = DefaultValue.bool(settings.hasBreaks, true);
    this.gearbox    = DefaultValue.string(settings.gearbox, 'manual');
    this.options    = DefaultValue.array(settings.options, []);

    // instead of doing this the hard way
    settings        = settings || {};
    this.wheels     = (!isNaN(settings.wheels)) ? settings.wheels : 4;
    this.hasBreaks  = (typeof settings.hasBreaks !== 'undefined') ? (settings.hasBreaks === true) : true;
    this.gearbox    = (typeof settings.gearbox === 'string') ? settings.gearbox : 'manual';
    this.options    = (typeof settings.options !== 'undefined' && Array.isArray(settings.options)) ? settings.options : [];
}

Usando essa classe:

(function(ns) {

    var DefaultValue = {

        object: function(input, defaultValue) {
            if (typeof defaultValue !== 'object') throw new Error('invalid defaultValue type');
            return (typeof input !== 'undefined') ? input : defaultValue;
        },

        bool: function(input, defaultValue) {
            if (typeof defaultValue !== 'boolean') throw new Error('invalid defaultValue type');
            return (typeof input !== 'undefined') ? (input === true) : defaultValue;
        },

        number: function(input, defaultValue) {
            if (isNaN(defaultValue)) throw new Error('invalid defaultValue type');
            return (typeof input !== 'undefined' && !isNaN(input)) ? parseFloat(input) : defaultValue;
        },

        // wrap the input in an array if it is not undefined and not an array, for your convenience
        array: function(input, defaultValue) {
            if (typeof defaultValue === 'undefined') throw new Error('invalid defaultValue type');
            return (typeof input !== 'undefined') ? (Array.isArray(input) ? input : [input]) : defaultValue;
        },

        string: function(input, defaultValue) {
            if (typeof defaultValue !== 'string') throw new Error('invalid defaultValue type');
            return (typeof input === 'string') ? input : defaultValue;
        },

    };

    ns.DefaultValue = DefaultValue;

}(this));

Eu não sei porque @ resposta de Paulo é downvoted, mas a validação contra null é uma boa escolha. Talvez um exemplo mais afirmativa fará mais sentido:

Em JavaScript um parâmetro perder é como uma variável declarou que não é inicializado (apenas var a1;). E os convertidos operador de igualdade o indefinido como nulo, então isso funciona muito bem com ambos os tipos de valor e objetos, e é assim CoffeeScript lida com parâmetros opcionais.

function overLoad(p1){
    alert(p1 == null); // Caution, don't use the strict comparison: === won't work.
    alert(typeof p1 === 'undefined');
}

overLoad(); // true, true
overLoad(undefined); // true, true. Yes, undefined is treated as null for equality operator.
overLoad(10); // false, false


function overLoad(p1){
    if (p1 == null) p1 = 'default value goes here...';
    //...
}

No entanto, há preocupações de que os melhores semântica é typeof variable === 'undefined' é um pouco melhor. Eu não estou prestes a defender esta, uma vez que é o problema da API subjacente como uma função é implementado; não deve interessar o usuário API.

Gostaria também de acrescentar que aqui é a única maneira de fisicamente certifique-se de qualquer argumento foram perdidas, usando o operador in que, infelizmente, não vai funcionar com os nomes dos parâmetros assim que tem de passar um índice da arguments.

function foo(a, b) {
    // Both a and b will evaluate to undefined when used in an expression
    alert(a); // undefined
    alert(b); // undefined

    alert("0" in arguments); // true
    alert("1" in arguments); // false
}

foo (undefined);

O teste para indefinido é desnecessária e não é tão robusto quanto poderia ser, porque, como user568458 apontou, a solução fornecida falha se nulo ou falso é passado. Os usuários do seu API pode pensar falsa ou nulo forçaria o método para evitar esse parâmetro.

function PaulDixonSolution(required, optionalArg){
   optionalArg = (typeof optionalArg === "undefined") ? "defaultValue" : optionalArg;
   console.log(optionalArg);
};
PaulDixonSolution("required");
PaulDixonSolution("required", "provided");
PaulDixonSolution("required", null);
PaulDixonSolution("required", false);

O resultado é:

defaultValue
provided
null
false

Aqueles dois últimos são potencialmente ruim. Em vez de tentar:

function bulletproof(required, optionalArg){
   optionalArg = optionalArg ? optionalArg : "defaultValue";;
   console.log(optionalArg);
};
bulletproof("required");
bulletproof("required", "provided");
bulletproof("required", null);
bulletproof("required", false);

o que resulta em:

defaultValue
provided
defaultValue
defaultValue

O único cenário em que este não é o ideal é quando você realmente tem parâmetros opcionais que se destinam a ser booleans ou nulo intencional.

Eu tentei algumas opções mencionadas aqui e desempenho testado eles. Neste momento, o logicalor parece ser o mais rápido. Embora este seja objecto de mudança ao longo do tempo (diferentes versões do motor de JavaScript).

Estes são os meus resultados (Microsoft Edge 20.10240.16384.0):

Function executed            Operations/sec     Statistics
TypeofFunction('test');          92,169,505     ±1.55%   9% slower
SwitchFuntion('test');            2,904,685     ±2.91%  97% slower
ObjectFunction({param1: 'test'});   924,753     ±1.71%  99% slower
LogicalOrFunction('test');      101,205,173     ±0.92%     fastest
TypeofFunction2('test');         35,636,836     ±0.59%  65% slower

Este teste de desempenho pode ser facilmente replicado em: http://jsperf.com/optional-parameters-typeof-vs-switch/ 2

Este é o código do teste:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script>
    Benchmark.prototype.setup = function() {
        function TypeofFunction(param1, optParam1, optParam2, optParam3) {
            optParam1 = (typeof optParam1 === "undefined") ? "Some default" : optParam1;
            optParam2 = (typeof optParam2 === "undefined") ? "Another default" : optParam2;
            optParam3 = (typeof optParam3 === "undefined") ? "Some other default" : optParam3;
        }

        function TypeofFunction2(param1, optParam1, optParam2, optParam3) {
            optParam1 = defaultValue(optParam1, "Some default");
            optParam2 = defaultValue(optParam2, "Another default");
            optParam3 = defaultValue(optParam3, "Some other default");
        }

        function defaultValue(variable, defaultValue) {
            return (typeof variable !== 'undefined') ? (variable) : (defaultValue);
        }

        function SwitchFuntion(param1, optParam1, optParam2, optParam3) {
            switch (arguments.length - 1) { // <-- 1 is number of required arguments
                case 0:
                    optParam1 = 'Some default';
                case 1:
                    optParam2 = 'Another default';
                case 2:
                    optParam3 = 'Some other default';
            }
        }

        function ObjectFunction(args) {
            var defaults = {
                optParam1: 'Some default',
                optParam2: 'Another default',
                optParam3: 'Some other default'
            }
            args = $.extend({}, defaults, args);
        }

        function LogicalOrFunction(param1, optParam1, optParam2, optParam3) {
            optParam1 || (optParam1 = 'Some default');
            optParam2 || (optParam1 = 'Another default');
            optParam3 || (optParam1 = 'Some other default');
        }
    };
</script>

Isto é o que eu acabei com:

function WhoLikesCake(options) {
  options = options || {};
  var defaultOptions = {
    a : options.a || "Huh?",
    b : options.b || "I don't like cake."
  }
  console.log('a: ' + defaultOptions.b + ' - b: ' + defaultOptions.b);

  // Do more stuff here ...
}

Chamado assim:

WhoLikesCake({ b : "I do" });

Pessoas -

Depois de olhar para estas e outras soluções, eu tentei um número de-los usando um trecho de código originalmente de W3Schools como base. Você pode encontrar o que funciona no seguinte. Cada um dos itens comentou o trabalho bem e são dessa forma para que você possa experimentar, basta remover comentários individuais. Para ser claro, é o parâmetro "eyecolor" que não está sendo definido.

function person(firstname, lastname, age, eyecolor)
{
this.firstname = firstname;
this.lastname = lastname;
this.age = age;
this.eyecolor = eyecolor;
// if(null==eyecolor)
//   this.eyecolor = "unknown1";
//if(typeof(eyecolor)==='undefined') 
//   this.eyecolor = "unknown2";
// if(!eyecolor)
//   this.eyecolor = "unknown3";
this.eyecolor = this.eyecolor || "unknown4";
}

var myFather = new person("John", "Doe", 60);
var myMother = new person("Sally", "Rally", 48, "green");

var elem = document.getElementById("demo");
elem.innerHTML = "My father " +
              myFather.firstname + " " +
              myFather.lastname + " is " +
              myFather.age + " with " +
              myFather.eyecolor + " eyes.<br/>" +
              "My mother " +
              myMother.firstname + " " +
              myMother.lastname + " is " +
              myMother.age + " with " +
              myMother.eyecolor + " eyes."; 
function Default(variable, new_value)
{
    if(new_value === undefined) { return (variable === undefined) ? null : variable; }
    return (variable === undefined) ? new_value : variable;
}

var a = 2, b = "hello", c = true, d;

var test = Default(a, 0),
test2 = Default(b, "Hi"),
test3 = Default(c, false),
test4 = Default(d, "Hello world");

window.alert(test + "\n" + test2 + "\n" + test3 + "\n" + test4);

http://jsfiddle.net/mq60hqrf/

Aqui está a minha solução. Com isso você pode deixar qualquer parâmetro que deseja. A ordem dos parâmetros opcionais não é importante e você pode adicionar validação personalizada.

function YourFunction(optionalArguments) {
            //var scope = this;

            //set the defaults
            var _value1 = 'defaultValue1';
            var _value2 = 'defaultValue2';
            var _value3 = null;
            var _value4 = false;

            //check the optional arguments if they are set to override defaults...
            if (typeof optionalArguments !== 'undefined') {

                if (typeof optionalArguments.param1 !== 'undefined')
                    _value1 = optionalArguments.param1;

                if (typeof optionalArguments.param2 !== 'undefined')
                    _value2 = optionalArguments.param2;

                if (typeof optionalArguments.param3 !== 'undefined')
                    _value3 = optionalArguments.param3;

                if (typeof optionalArguments.param4 !== 'undefined')
                    //use custom parameter validation if needed, in this case for javascript boolean
                   _value4 = (optionalArguments.param4 === true || optionalArguments.param4 === 'true');
            }

            console.log('value summary of function call:');
            console.log('value1: ' + _value1);
            console.log('value2: ' + _value2);
            console.log('value3: ' + _value3);
            console.log('value4: ' + _value4);
            console.log('');
        }


        //call your function in any way you want. You can leave parameters. Order is not important. Here some examples:
        YourFunction({
            param1: 'yourGivenValue1',
            param2: 'yourGivenValue2',
            param3: 'yourGivenValue3',
            param4: true,
        });

        //order is not important
        YourFunction({
            param4: false,
            param1: 'yourGivenValue1',
            param2: 'yourGivenValue2',
        });

        //uses all default values
        YourFunction();

        //keeps value4 false, because not a valid value is given
        YourFunction({
            param4: 'not a valid bool'
        });
  1. arg || 'default' é uma ótima maneira e funciona por 90% dos casos

  2. Ele falha quando você precisa passar valores que podem ser 'Falsas'

    • false
    • 0
    • NaN
    • ""

    Para esses casos, você precisa ser um pouco mais detalhado e verificar se há undefined

  3. Também deve ter cuidado quando você tem argumentos opcionais em primeiro lugar, você tem que estar ciente dos tipos de todos os seus argumentos

Em todos os casos em que optionalArg é Falsas você vai acabar com defaultValue.

function myFunc(requiredArg, optionalArg) {
    optionalArg = optionalArg || 'defaultValue';
    console.log(optionalArg);
    // Do stuff
}
myFunc(requiredArg);
myFunc(requiredArg, null);
myFunc(requiredArg, undefined);
myFunc(requiredArg, "");
myFunc(requiredArg, 0);
myFunc(requiredArg, false);

Todo o log acima defaultValue, porque todos os 6 são Falsas. No caso 4, 5, 6, você pode não estar interessado em optionalArg conjunto como defaultValue, mas define uma vez que são Falsas.

me corrija se eu estiver errado, mas esta parece ser a maneira mais simples (para um argumento, de qualquer maneira):

function myFunction(Required,Optional)
{
    if (arguments.length<2) Optional = "Default";
    //Your code
}

Aqueles são mais curtos do que a versão do operador typeof.

function foo(a, b) {
    a !== undefined || (a = 'defaultA');
    if(b === undefined) b = 'defaultB';
    ...
}

Eu sugiro que você use ArgueJS desta maneira:

function myFunc(){
  arguments = __({requiredArg: undefined, optionalArg: [undefined: 'defaultValue'})

  //do stuff, using arguments.requiredArg and arguments.optionalArg
  //    to access your arguments

}

Você também pode substituir undefined pelo tipo do argumento que você espera receber, como este:

function myFunc(){
  arguments = __({requiredArg: Number, optionalArg: [String: 'defaultValue'})

  //do stuff, using arguments.requiredArg and arguments.optionalArg
  //    to access your arguments

}

Parece que a forma mais segura - para lidar com todos os \ qualquer tipos Falsas de fornecido argumentos antes de decidir usar o padrão - é verificar a existência \ presença do argumento opcional na função invocada.

Baseando-se na criação membro argumentos objeto que nem sequer são criados se o argumento está faltando, independentemente do fato de que ele pode ser declarado, podemos escrever a sua função como esta:

  function myFunc(requiredArg, optionalArg){
        optionalArg = 1 in arguments ? optionalArg : 'defaultValue';
  //do stuff
  }

Utilizando este comportamento: Podemos verificar com segurança para quaisquer valores em falta na lista de argumentos arbitrariamente e explicitamente sempre que precisamos para garantir que a função recebe um determinado valor exigido em seu procedimento.

No seguinte demonstração código vamos deliberadamente colocar um typeless e sem valor indefinido como um valor padrão para ser capaz de determinar se ele pode falhar em valores de argumento falsas, como 0 false etc., ou se ele se comporta como esperado.

function argCheck( arg1, arg2, arg3 ){

       arg1 = 0 in arguments || undefined;
       arg2 = 1 in arguments || false;
       arg3 = 2 in arguments || 0;
   var arg4 = 3 in arguments || null;

   console.log( arg1, arg2, arg3, arg4 ) 
}

Agora, verificando alguns valores de argumento Falsas para ver se a sua presença é detectada corretamente e, portanto, avalia a true :

argCheck( "", 0, false, null );
>> true true true true

O que significa -eles não deixou o reconhecimento dos / as os valores dos argumentos esperados. Aqui temos um cheque com todos os argumentos em falta, que de acordo com o nosso algo devem adquirir seus valores padrão, mesmo se eles são Falsas .

argCheck( );
>> undefined false 0 null

Como podemos ver, os argumentos arg1, arg2, arg3 e não-declarado arg4 , estão retornando a sua exata padrão valores, como ordenado. Porque nós temos agora a certeza de que ele funciona, podemos reescrever a função que irá realmente ser capaz de usá-los como no primeiro exemplo usando: ou se ou um ternário condição.

Em funções que têm mais de um argumento opcional, - um circuito completamente, poderia ter nos salvou alguns bits. Mas desde argumento nomes não se inicializado se seus valores não são fornecidos, não podemos acessá-los por nomes mais mesmo se nós programaticamente escrito um valor padrão, nós podemos única acessá-los por argumentos [índice] que a legibilidade do código inútil sábio.

Mas, além de este inconveniente, que em determinadas situações de codificação pode ser totalmente aceitável, há outro problema desaparecidos vários números e arbitrário de padrões de argumento. Que pode e deve ser considerado um erro, como não podemos mais ignorar argumentos, assim como nós já poderia ter sido capaz de, sem dar um valor, em uma sintaxe como:

argCheck("a",,22,{});

porque ele vai jogar! O que torna impossível para nós para substituir a nossa discussão com um determinado Falsas digite do nosso valor padrão desejado. Que é estúpido, uma vez que o argumentos objeto é uma matriz-como objeto e é esperado para suportar esta sintaxe e convenções como é, nativamente ou por padrão!

Por causa desta decisão míope não podemos mais esperança para escrever uma função como esta:

function argCheck( ) {
    var _default = [undefined, 0, false, null ],
        _arg = arguments;

 for( var x in _default ) {
         x in _arg ? 1 : _arg[x] = _default[x];
        }
    console.log( _arg[0],_arg[1],_arg[2],_arg[3] );
}

nesse caso, que seria capaz de escrever cada valor padrão de um tipo desejado em argumentos de linha e ser capaz de, pelo menos, o acesso deles por args.index.

Por exemplo dessa chamada de função renderia:

argCheck();
>>undefined 0 false null

conforme definido na nossa gama padrão de valores argumentos. No entanto, o seguinte ainda é possível:

argCheck({})
>>Object {  } 0 false null

argCheck({}, [])
>>Object {  } Array [  ] false null

Mas infelizmente não:

 argCheck("a",,,22);
 >>SyntaxError: expected expression, got ','

O que de outra forma seria o registo:

>>a 0 false 22

Mas isso é em um mundo melhor! No entanto - para a pergunta original - a função de nível superior vai fazer muito bem. por exemplo:.

function argCheck( arg, opt ) {
         1 in arguments ? 1 : opt = "default";
         console.log( arg, opt );
}

P.S .: pena de não preservar os tipos de padrões escolhidos em minhas entradas argumento enquanto escrevê-los.

function foo(requiredArg){
  if(arguments.length>1) var optionalArg = arguments[1];
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top