Есть ли лучший способ сделать необязательные параметры функции в JavaScript?[дубликат]

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

  •  02-07-2019
  •  | 
  •  

Вопрос

На этот вопрос уже есть ответ здесь:

Я всегда обрабатывал необязательные параметры в JavaScript следующим образом:

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

  // Do stuff
}

Есть ли лучший способ сделать это?

Есть ли какие-либо случаи, когда использование || как будто это обречено на провал?

Это было полезно?

Решение

Ваша логика завершается сбоем, если передается optionalArg, но вычисляется как false - попробуйте это в качестве альтернативы

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

Или альтернативная идиома:

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

Используйте ту идиому, которая лучше всего передает ваше намерение!

Другие советы

В ECMAScript 2015 (он же "ES6") вы можете объявлять значения аргументов по умолчанию в объявлении функции:

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

Подробнее о них читайте в эта статья о MDN.

В настоящее время это поддерживается только Firefox, но по мере завершения разработки стандарта ожидайте быстрого улучшения поддержки.

РЕДАКТИРОВАТЬ (2019-06-12):

Параметры по умолчанию в настоящее время широко поддерживаются современными браузерами.Все версии Internet Explorer не поддерживают эту функцию.Однако в настоящее время Chrome, Firefox и Edge поддерживают его.

Я считаю, что это самый простой и удобочитаемый способ:

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

Ответ Пола Диксона (по моему скромному мнению) менее читабелен, чем этот, но все сводится к предпочтениям.

ответ инсина намного более продвинутый, но гораздо более полезный для больших функций!

РЕДАКТИРОВАТЬ 17.11.2013 9:33 вечера: Я создал пакет для Node.js, который упрощает "перегрузку" вызываемых функций (методов) параметрический.

Если вам нужно выбросить буквальное NULL во, тогда у вас могут возникнуть некоторые проблемы.Кроме того, нет, я думаю, что вы, вероятно, на правильном пути.

Другой метод, который выбирают некоторые люди, - это получение ассоциативного массива переменных, повторяющегося по списку аргументов.Это выглядит немного аккуратнее, но я предполагаю, что это немного (очень немного) требует больше ресурсов процесса / памяти.

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];

    // ...
}

В идеале вы бы провели рефакторинг, чтобы передать объект и слияние это с объектом по умолчанию, поэтому порядок, в котором передаются аргументы, не имеет значения (см. Второй раздел этого ответа ниже).

Однако, если вам просто нужно что-то быстрое, надежное, простое в использовании и не громоздкое, попробуйте это:


Чистое быстрое исправление для любого количества аргументов по умолчанию

  • Он элегантно масштабируется:минимальный дополнительный код для каждого нового значения по умолчанию
  • Вы можете вставить его куда угодно:просто измените количество требуемых аргументов и переменных
  • Если вы хотите пройти undefined таким образом, для аргумента со значением по умолчанию переменная устанавливается как undefined.Большинство других опций на этой странице заменили бы undefined со значением по умолчанию.

Вот пример предоставления значений по умолчанию для трех необязательных аргументов (с двумя обязательными аргументами)

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
  }

}

Простая демонстрация.Это похоже на ответ ренвинга, но легко расширяемый для любого количества аргументов по умолчанию, более простой в обновлении и используя arguments нет Function.arguments.


Передача и объединение объектов для большей гибкости

Приведенный выше код, как и многие способы использования аргументов по умолчанию, не может передавать аргументы вне последовательности, например, передавая optionalC но уходя optionalB вернуться к своему умолчанию.

Хорошим вариантом для этого является передача объектов и слияние с объектом по умолчанию.Это также полезно для удобства сопровождения (просто следите за тем, чтобы ваш код был читабельным, чтобы будущим сотрудникам не приходилось гадать о возможном содержимом объектов, которые вы передаете).

Пример использования jQuery.Если вы не используете jQuery, вы могли бы вместо этого использовать символ подчеркивания _.defaults(object, defaults) или просмотрите эти параметры:

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

Вот простой пример этого в действии.

Для этого вы можете использовать несколько различных схем.Я всегда проверял наличие аргументов.длина:

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

  ...

-- при таком подходе он не может потерпеть неудачу, но я не знаю, есть ли у вашего способа хоть какой-то шанс на неудачу, просто сейчас я не могу придумать сценарий, при котором он действительно потерпел бы неудачу...

И тогда Пол предложил один неудачный сценарий !-)

Подобно ответу Оли, я использую объект-аргумент и объект, который определяет значения по умолчанию.С небольшим количеством сахара...

/**
 * 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
}

..это можно сделать немного приятнее.

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)

Что хорошего в этом методе?

  • Вы можете опустить столько аргументов, сколько захотите - если вы хотите переопределить значение только одного аргумента, вы можете просто указать этот аргумент вместо того, чтобы явно передавать undefined когда, скажем, есть 5 аргументов, и вы хотите настроить только последний, как вам пришлось бы поступить с некоторыми другими предложенными методами.
  • При работе с функцией-конструктором для объекта, который наследуется от другого, легко принять любые аргументы, которые требуются конструктору объекта, от которого вы наследуете, поскольку вам не нужно называть эти аргументы в подписи вашего конструктора или даже указывать свои собственные значения по умолчанию (пусть конструктор родительского объекта сделает это за вас, как показано выше, когда CharField звонки Fieldконструктор).
  • Дочерние объекты в иерархиях наследования могут настраивать аргументы для своего родительского конструктора по своему усмотрению, применяя свои собственные значения по умолчанию или гарантируя, что определенное значение будет всегда быть использованным.

Если вы широко используете значения по умолчанию, это кажется гораздо более читабельным:

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;
}

Просто объявите эту функцию в глобальном escope.

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

Схема использования fruit = defaultValue(fruit,'Apple');

*PS вы можете переименовать defaultValue используйте функцию с коротким именем, просто не используйте default это зарезервированное слово в javascript.

Проверка незакрепленного типа

Легко писать, но 0, '', false, null и undefined будет преобразовано в значение по умолчанию, которое, возможно, не является ожидаемым результатом.

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

Строгая проверка типа

Длиннее, но охватывает большинство случаев.Единственный случай, когда он неправильно присваивает значение по умолчанию, - это когда мы передаем undefined в качестве параметра.

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

Проверка аргументов переменной

Улавливает все случаи, но наиболее неуклюж в написании.

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

ES6

К сожалению, на данный момент у этого браузера очень плохая поддержка

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

}

С ES2015 / ES6 вы можете воспользоваться преимуществами Object.assign который может заменить $.extend() или _.defaults()

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

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

  // do stuff
}

Вы также можете использовать аргументы по умолчанию, подобные этому

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

Я привык видеть несколько основных вариантов обработки необязательных переменных.Иногда полезны смягченные версии.

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.
}

Ложное значение по умолчанию, используемое с переменной a широко используется, например, в Backbone.js.

Если вы используете Подчеркивание библиотека (вы должны, это потрясающая библиотека):

_.defaults(optionalArg, 'defaultValue');

Приземлился на этот вопрос, ища параметры по умолчанию в ECMAScript 2015, таким образом, просто упоминая...

С ES6 мы можем сделать параметры по умолчанию:

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

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

Во время проекта я заметил, что слишком часто повторяюсь с необязательными параметрами и настройками, поэтому я создал класс, который обрабатывает проверку типов и присваивает значение по умолчанию, что приводит к аккуратному и читабельному коду.Посмотрите пример и дайте мне знать, если это сработает для вас.

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 : [];
}

Используя этот класс:

(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));

Я не знаю, почему ответ @Paul отклонен, но проверка против null это хороший выбор.Может быть, более утвердительный пример будет иметь больше смысла:

В JavaScript пропущенный параметр подобен объявленной переменной, которая не инициализирована (просто var a1;).А оператор равенства преобразует значение undefined в значение null, так что это отлично работает как с типами значений, так и с объектами, и именно так CoffeeScript обрабатывает необязательные параметры.

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...';
    //...
}

Тем не менее, есть опасения, что для лучшей семантики typeof variable === 'undefined' это немного лучше.Я не собираюсь защищать это, поскольку это зависит от базового API, как реализована функция;это не должно интересовать пользователя API.

Я должен также добавить, что вот единственный способ физически убедиться, что какой-либо аргумент был пропущен, используя in оператор, который, к сожалению, не будет работать с именами параметров, поэтому должен передать индекс 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);

Тест для undefined не является необходимым и не является таким надежным, каким мог бы быть, потому что, как указал пользователь568458, предоставленное решение завершается с ошибкой, если передается значение null или false.Пользователи вашего API могут подумать, что значение false или null заставит метод избегать этого параметра.

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

В результате получается:

defaultValue
provided
null
false

Эти последние два потенциально плохи.Вместо этого попробуйте:

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

Что приводит к:

defaultValue
provided
defaultValue
defaultValue

Единственный сценарий, в котором это не является оптимальным, - это когда у вас на самом деле есть необязательные параметры, которые должны быть логическими или намеренно равными нулю.

Я попробовал несколько вариантов, упомянутых здесь, и протестировал их производительность.На данный момент логический процесс кажется самым быстрым.Хотя это может изменяться с течением времени (разные версии движка JavaScript).

Это мои результаты (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

Этот тест производительности может быть легко воспроизведен на:http://jsperf.com/optional-parameters-typeof-vs-switch/2

Это код теста:

<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>

Вот с чем я в итоге столкнулся:

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 ...
}

Называется вот так:

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

Люди -

Рассмотрев эти и другие решения, я опробовал некоторые из них, используя в качестве основы фрагмент кода, изначально взятый из W3Schools.Вы можете найти, что работает, в следующем разделе.Каждый из закомментированных элементов также работает, и это позволяет вам экспериментировать, просто удаляя отдельные комментарии.Чтобы было понятно, это параметр "eyecolor", который не определяется.

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/

Вот мое решение.При этом вы можете оставить любой параметр, который вы хотите.Порядок необязательных параметров не важен, и вы можете добавить пользовательскую проверку.

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' это отличный способ и работает в 90% случаев

  2. Это приводит к сбою, когда вам нужно передать значения, которые могут быть "ложными"

    • false
    • 0
    • NaN
    • ""

    В этих случаях вам нужно будет быть немного более подробным и проверить наличие undefined

  3. Также будьте осторожны, когда у вас сначала есть необязательные аргументы, вы должны быть осведомлены о типах всех ваших аргументов

Во всех случаях, когда значение optionalArg является ложным, вы получите значение 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);

Все вышеприведенные значения регистрируют defaultValue, потому что все 6 являются ложными.В случае 4, 5, 6 вам может быть неинтересно устанавливать optionalArg в качестве defaultValue, но он устанавливается, поскольку они являются ложными.

Поправьте меня, если я ошибаюсь, но это кажется самым простым способом (во всяком случае, для одного аргумента).:

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

Эти значения короче, чем версия оператора typeof.

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

Я предлагаю вам использовать Аргументы сюда:

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

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

}

Вы также можете заменить undefined по типу аргумента, который вы ожидаете получить, например, так:

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

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

}

Кажется, что самый безопасный способ - разобраться со всеми\любым ложные типы из поставляемых аргументы прежде чем принять решение использовать По умолчанию - заключается в проверке наличия необязательный аргумент в вызываемой функции.

Полагаясь на создание элемента объекта arguments, который даже не создается, если аргумент отсутствует, независимо от того факта, что он может быть объявлен, мы можем написать вашу функцию следующим образом:

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

Используя это поведение:Мы можем безопасно проверять наличие любых отсутствующих значений в списке аргументов произвольно и явно всякий раз, когда нам нужно убедиться, что функция получает определенное значение, требуемое в ее процедуре.

В следующем демонстрационном коде мы намеренно добавим безтипный и бесполезный неопределенный в качестве значения по умолчанию, чтобы иметь возможность определить, может ли произойти сбой при ложных значениях аргументов, таких как 0 false и т.д., или оно ведет себя так, как ожидалось.

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 ) 
}

Теперь, проверяя несколько ложных значений аргументов, чтобы увидеть, правильно ли обнаружено их присутствие и, следовательно, оценивается как верно:

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

Это означает, что они не ошиблись в распознавании / как ожидаемых значений аргументов.Здесь у нас есть проверка с отсутствующими всеми аргументами, которые, согласно нашему алгоритму, должны приобретать значения по умолчанию, даже если они фальшивый.

argCheck( );
>> undefined false 0 null

Как мы можем видеть, аргументы арг1, арг2, арг3 и необъявленный arg4, возвращают свои точные По умолчанию значения, как заказано.Поскольку теперь мы убедились, что это работает, мы можем переписать функцию, которая действительно сможет использовать их, как в первом примере, используя:либо если или троичный состояние.

Для функций, которые имеют более одного необязательного аргумента, - сквозной цикл, возможно, сэкономил бы нам некоторые биты.Но поскольку аргумент имена не инициализируются, если их значения не указаны, мы больше не можем обращаться к ним по именам, даже если мы программно написали значение по умолчанию, мы можем обращаться к ним только по аргументы [индекс] что бесполезно с точки зрения удобочитаемости кода.

Но помимо этого неудобства, которое в определенных ситуациях кодирования может быть полностью приемлемым, существует еще одна неучтенная проблема для множественных и произвольных значений аргументов по умолчанию.Что может и должно рассматриваться как ошибка, поскольку мы больше не можем пропускать аргументы, как когда-то могли бы, не указывая значения, в таком синтаксисе, как:

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

потому что его выбросят!Что делает для нас невозможным заменить наш аргумент конкретным фальшивый введите желаемое значение по умолчанию.Что глупо, поскольку аргументы объекта является массивоподобным объектом и, как ожидается, будет поддерживать этот синтаксис и соглашение как есть, изначально или по умолчанию!

Из-за этого недальновидного решения мы больше не можем надеяться на написание подобной функции:

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] );
}

в этом случае мы могли бы записать каждое значение по умолчанию нужного типа в строку arguments и иметь возможность, по крайней мере, обращаться к ним с помощью args.index.

Например, вызов этой функции привел бы к:

argCheck();
>>undefined 0 false null

как определено в нашем массиве значений аргументов по умолчанию.Однако по-прежнему возможно следующее:

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

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

Но , к сожалению, нет:

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

Который в противном случае вел бы протоколирование:

>>a 0 false 22

но это в лучшем мире!Однако - для исходного вопроса - самая верхняя функция будет работать просто отлично.например ,:

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

p.s.:извините, что не сохранил типы выбранных значений по умолчанию во входных данных моих аргументов при их написании.

function foo(requiredArg){
  if(arguments.length>1) var optionalArg = arguments[1];
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top