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

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

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

  // Do stuff
}

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

Есть ли случаи, когда с помощью || как это потерпит неудачу?

Ответ 1

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

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

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

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

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

Ответ 2

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

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

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

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

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

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

Ответ 3

Я считаю, что это самый простой и понятный способ:

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

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

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

EDIT 11/17/2013 9:33 вечера: Я создал пакет для Node.js, который упрощает "перегрузку" функций (методов), называемых parametric.

Ответ 4

Если вам нужно вытащить буквальный 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];

    // ...
}

Ответ 5

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

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


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

  • Он масштабируется элегантно: минимальный дополнительный код для каждого нового значения по умолчанию
  • Вы можете вставить его в любом месте: просто измените количество требуемых аргументов и переменных
  • Если вы хотите передать 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
  }

}

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


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

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

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

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

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

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

Ответ 6

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

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

  ...

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

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

Ответ 7

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

/**
 * Updates an object 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 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 аргументов, и вы только хотите настроить последний, так как вам придется делать некоторые из других предложенных методов.
  • При работе с конструктором Function для объекта, который наследуется от другого, легко принять любые аргументы, которые требуются конструктору объекта, на который вы наследуете, поскольку вам не нужно называть эти аргументы в вашем подпись конструктора или даже предоставить свои собственные значения по умолчанию (пусть родительский конструктор объектов сделает это для вас, как показано выше, когда CharField вызывает конструктор Field).
  • Дочерние объекты в иерархиях наследования могут настраивать аргументы для своего родительского конструктора по своему усмотрению, применяя собственные значения по умолчанию или гарантируя, что определенное значение всегда будет использоваться.

Ответ 8

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

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

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

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

Шаблон использования fruit = defaultValue(fruit,'Apple');

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

Ответ 9

Проверка свободного типа

Легко писать, но 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') {

}

Ответ 10

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

Ответ 11

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

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.

Ответ 12

Если вы используете библиотеку Underscore (вы должны сделать это замечательной библиотекой):

_.defaults(optionalArg, 'defaultValue');

Ответ 13

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

В JavaScript пропущенный параметр похож на объявленную переменную, которая не инициализируется (просто var a1;). А оператор равенства преобразует неопределенное в нулевое, так что это прекрасно работает как с типами значений, так и с объектами, и именно так 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);

Ответ 14

Проверка на undefined не нужна и не так надежна, как могла бы быть, потому что, как указал user568458, предоставленное решение завершается неудачно, если передано значение 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

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

Ответ 15

Я попробовал некоторые варианты, упомянутые здесь, и тестировал их производительность. В этот момент логика кажется самой быстрой. Хотя со временем это может измениться (разные версии движка 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>

Ответ 16

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

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

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

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

Ответ 17

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

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

Ответ 18

Вот что я закончил:

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

Ответ 19

Люди -

Посмотрев на эти и другие решения, я попробовал несколько из них, используя фрагмент кода, первоначально из 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."; 

Ответ 20

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/

Ответ 21

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

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

Ответ 22

  • arg || 'default' - отличный способ и работает в 90% случаев

  • Он терпит неудачу, когда вам нужно передать значения, которые могут быть "ложными"

    • false
    • 0
    • NaN
    • ""

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

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

Ответ 23

Во всех случаях, когда optionArg является ложным, вы получите 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 вам может быть не интересно устанавливать опциональное значение Arg как defaultValue, но оно устанавливается, поскольку они ложные.

Ответ 24

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

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

Ответ 25

Эти версии короче версии оператора typeof.

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

Ответ 26

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

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

}

Ответ 27

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

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

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

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

В следующем демо-коде мы намеренно помещаем в значение по умолчанию значение undefined без значения undefined, чтобы определить, может ли он терпеть неудачу по значениям ложных аргументов, например 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 ) 
}

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

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

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

argCheck( );
>> undefined false 0 null

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

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

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

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

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

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

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

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

Ответ 28

Некоторые интеллектуальные инструменты кода, в частности, IDE WebStorm и, возможно, jshint, предоставляют предупреждения, когда вы вызываете функцию с меньшими аргументами, чем объявлено:

function foo(a, b) {
    if (typeof b === 'undefined') {
        b = 5;
    }
    …
}

foo(1); /* warning */

Вместо этого вы можете:

function foo(a /*, b */) {
    var b = arguments.length > 1 ? arguments[1] : 2;
    …
}

foo(1);

Обратите внимание, что аргумент b объявлен в комментарии для ясности.

Ответ 29

function foo(requiredArg){
  if(arguments.length>1) var optionalArg = arguments[1];
}