Установите значение параметра по умолчанию для функции JavaScript

2148

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

def read_file(file, delete_after = false)
  # code
end

Это работает в JavaScript?

function read_file(file, delete_after = false) {
  // Code
}
Теги:
function
parameters
default-parameters

22 ответа

3075
Лучший ответ

Из ES6/ES2015 параметры по умолчанию указаны в спецификации языка.

function read_file(file, delete_after = false) {
  // Code
}

просто работает.

Ссылка: Параметры по умолчанию - MDN

Параметры функции по умолчанию позволяют инициализировать формальные параметры со значениями по умолчанию, если передано no value или undefined.

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

// the `= {}` below lets you call the function without any parameters
function myFor({ start = 5, end = 1, step = -1 } = {}) { // (A)
    // Use the variables `start`, `end` and `step` here
    ···
}

Pre ES2015,

Есть много способов, но это мой предпочтительный метод - он позволяет передавать все, что угодно, включая false или null. (typeof null == "object")

function foo(a, b) {
  a = typeof a !== 'undefined' ? a : 42;
  b = typeof b !== 'undefined' ? b : 'default_b';
  ...
}
  • 202
    Вы также можете инкапсулировать это так: function defaultFor(arg, val) { return typeof arg !== 'undefined' ? arg : val; } и затем вы можете вызвать его как a = defaultFor(a, 42);
  • 1
    Это слишком медленно, используйте a = ((a != null) ? a : 42); ,
Показать ещё 21 комментарий
606
function read_file(file, delete_after) {
    delete_after = delete_after || "my default here";
    //rest of code
}

Это присваивает delete_after значение delete_after, если оно не является ложным значением, иначе оно назначает строку "my default here". Для более подробной информации ознакомьтесь с обзором Doug Crockford языка и ознакомьтесь с разделом об операторах.

Этот подход не работает, если вы хотите передать значение false, т.е. false, null, undefined, 0 или "". Если вам требуются значения ложности, которые вам нужно передать, вам нужно будет использовать метод в ответе Тома Риттера.

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

function read_file(values) {
    values = merge({ 
        delete_after : "my default here"
    }, values || {});

    // rest of code
}

// simple implementation based on $.extend() from jQuery
function merge() {
    var obj, name, copy,
        target = arguments[0] || {},
        i = 1,
        length = arguments.length;

    for (; i < length; i++) {
        if ((obj = arguments[i]) != null) {
            for (name in obj) {
                copy = obj[name];

                if (target === copy) {
                    continue;
                }
                else if (copy !== undefined) {
                    target[name] = copy;
                }
            }
        }
    }

    return target;
};

использовать

// will use the default delete_after value
read_file({ file: "my file" }); 

// will override default delete_after value
read_file({ file: "my file", delete_after: "my value" }); 
  • 110
    Я нахожу это недостаточным, потому что я могу перейти в ложь.
  • 52
    Я считаю, что это подходит для большинства ситуаций
Показать ещё 15 комментариев
150

Я нахожу что-то простое, как это, гораздо более сжатым и читаемым лично.

function pick(arg, def) {
   return (typeof arg == 'undefined' ? def : arg);
}

function myFunc(x) {
  x = pick(x, 'my default');
} 
  • 6
    Обновление: если вы уже используете underscore.js, я считаю, что еще лучше использовать _.defaults(iceCream, {flavor: "vanilla", sprinkles: "lots"}); , Использование глобального пространства имен, как показано в этом ответе, многими считается плохой практикой. Вы также можете рассмотреть возможность использования своей собственной утилиты для этой общей задачи (например, util.default(arg, "defaul value") ), если вы не хотите использовать подчеркивание, но я в основном заканчиваю тем, что рано или поздно использую подчеркивание, так или иначе, нет смысла заново изобретать колесо.
  • 0
    @andersand Мне нравится идея что-то вроде util.default(arg, "defaul value")) Вы или @ tj111 не возражаете опубликовать быструю демоверсию?
Показать ещё 5 комментариев
58

В ECMAScript 6 вы действительно сможете написать именно то, что у вас есть:

function read_file(file, delete_after = false) {
  // Code
}

Это установит delete_after в false, если оно отсутствует или undefined. Вы можете использовать такие функции ES6, как сегодня, с транспилерами, такими как Babel.

Подробнее см. статью MDN.

  • 1
    ECMAScript 6 Полагаю ... (я бы исправил сам, но не могу внести изменения <6 символов)
  • 1
    В ожидании браузера любой получить ECMAScript 6
Показать ещё 5 комментариев
24

Значения параметров по умолчанию

С ES6 вы можете сделать, возможно, одна из самых распространенных идиом в JavaScript связана с установкой значения по умолчанию для параметра функции. То, как мы это делали в течение многих лет, должно выглядеть довольно знакомо:

function foo(x,y) {
 x = x || 11;
 y = y || 31;
 console.log( x + y );
}
foo(); // 42
foo( 5, 6 ); // 11
foo( 5 ); // 36
foo( null, 6 ); // 17

Этот шаблон наиболее часто используется, но он опасен, когда мы передаем значения, например

foo(0, 42)
foo( 0, 42 ); // 53 <-- Oops, not 42

Почему? Потому что 0 is falsy и т.д. x || 11 results in 11, а не непосредственно переданный в 0. Чтобы исправить эту ошибку, некоторые люди вместо этого напишут проверку более подробно:

function foo(x,y) {
 x = (x !== undefined) ? x : 11;
 y = (y !== undefined) ? y : 31;
 console.log( x + y );
}
foo( 0, 42 ); // 42
foo( undefined, 6 ); // 17

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

function foo(x = 11, y = 31) {
 console.log( x + y );
}

foo(); // 42
foo( 5, 6 ); // 11
foo( 0, 42 ); // 42
foo( 5 ); // 36
foo( 5, undefined ); // 36 <-- `undefined` is missing
foo( 5, null ); // 5 <-- null coerces to `0`
foo( undefined, 6 ); // 17 <-- `undefined` is missing
foo( null, 6 ); // 6 <-- null coerces to `0`

x = 11 в объявлении функции больше похож на x !== undefined ? x : 11, чем на гораздо более распространенную идиому x || 11

Выражения по умолчанию

Function значения по умолчанию могут быть больше, чем просто простые значения, такие как 31; они могут быть любым допустимым выражением, даже a function call:

function bar(val) {
 console.log( "bar called!" );
 return y + val;
}
function foo(x = y + 3, z = bar( x )) {
 console.log( x, z );
}
var y = 5;
foo(); // "bar called"
 // 8 13
foo( 10 ); // "bar called"
 // 10 15
y = 6;
foo( undefined, 10 ); // 9 10

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

Выражение по умолчанию может быть даже вызовом выражения встроенной функции - обычно называется выражением с выраженной немедленной функцией (IIFE):

function foo( x =
 (function(v){ return v + 11; })( 31 )
) {
 console.log( x );
}
foo(); // 42
10

это решение работает для меня в js:

function read_file(file, delete_after) {
    delete_after = delete_after || false;
    // Code
}
  • 4
    Что произойдет, если delete_after равен 0 или равен null ? Это не будет работать правильно для этих случаев.
  • 0
    @StephanBijzitter это было бы верно только в некоторых случаях. Но если вы хотите, чтобы только значения по умолчанию сбрасывали значения, это не сработало, потому что 0 или ноль! === false.
Показать ещё 2 комментария
9

Просто используйте явное сравнение с undefined.

function read_file(file, delete_after)
{
    if(delete_after === undefined) { delete_after = false; }
}
7

Я очень рекомендую предельную осторожность при использовании значений параметров по умолчанию в javascript. Он часто создает ошибки, когда используется в сочетании с функциями более высокого порядка, такими как forEach, map и reduce. Например, рассмотрим эту строку кода:

['1', '2', '3'].map(parseInt); // [1, NaN, NaN]

У parseInt есть необязательная function parseInt(s, [ второго параметра function parseInt(s, [ radix =10]) но карта вызывает parseInt с тремя аргументами: (элемент, индекс и массив).

Я предлагаю вам отделить необходимые параметры от необязательных/значений по умолчанию. Если ваша функция принимает 1,2 или 3 обязательных параметра, для которых значение по умолчанию не имеет смысла, сделайте их позиционными параметрами для функции, любые дополнительные параметры должны следовать как именованные атрибуты одного объекта. Если вашей функции требуется 4 или более, возможно, имеет смысл предоставить все аргументы через атрибуты одного параметра объекта.

В вашем случае я бы предложил вам написать функцию deleteFile следующим образом: (отредактировано instead комментариев)...

// unsafe
function read_file(fileName, deleteAfter=false) {
    if (deleteAfter) {
        console.log('Reading and then deleting ${fileName}');
    } else {
        console.log('Just reading ${fileName}');
    }
}

// better
function readFile(fileName, options) {
  const deleteAfter = !!(options && options.deleteAfter === true);
  read_file(fileName, deleteAfter);
}

console.log('unsafe...');
['log1.txt', 'log2.txt', 'log3.txt'].map(read_file);

console.log('better...');
['log1.txt', 'log2.txt', 'log3.txt'].map(readFile);

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

  • 0
    Это «лучшее решение» совершенно нечитаемо. Я бы порекомендовал проверить тип переменной, такой как typeof deleteAfter === 'bool' и в противном случае typeof deleteAfter === 'bool' исключение. Плюс в случае использования таких методов, как map / foreach и т. Д., Просто используйте их с осторожностью и оберните вызываемые функции анонимной функцией. ['1', '2', '3'].map((value) => {read_file(value);})
  • 0
    Неплохо подмечено. Я пытался избежать использования библиотек в моем фрагменте кода, но эта идиома довольно грязная в чистом javascript. Лично я бы использовал метод get lodash для извлечения deleteAfter. Бросок исключения, если typeof 'deleteAfter' !== 'bool' также может быть хорошей разумной мерой. Мне не нравится разрабатывать методы, которые требуют от вызывающего абонента "проявлять осторожность". Ответственность лежит на функции, а не на вызывающем абоненте. Конечное поведение должно следовать принципу наименьшего удивления.
Показать ещё 1 комментарий
7

являющийся разработчиком С++ долгое время (Rookie to web development:)), когда я впервые столкнулся с этой ситуацией, я сделал назначение параметров в определении функции, как это указано в вопросе, следующим образом.

function myfunc(a,b=10)

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

    function myfunc(a,b)
    {
    if (typeof(b)==='undefined') b = 10;
......
    }

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

  • 3
    Назначение в определении функции также не работает в IE 11, который является самой последней версией IE для Windows 8.1.
  • 1
    Если кому-то интересно, function myfunc(a,b=10) имеет синтаксис ES6, в других ответах есть ссылки на таблицы совместимости.
7

В качестве обновления... с ECMAScript 6 вы можете ПОЛНОСТЬЮ установить значения по умолчанию в объявлениях параметров функции следующим образом:

function f (x, y = 7, z = 42) {
  return x + y + z
}

f(1) === 50

Как упоминалось - http://es6-features.org/#DefaultParameterValues

  • 10
    Этот ответ не является полезным, потому что это дубликат
6

Для всех, кто заинтересован в работе с кодом в Microsoft Edge, не используйте значения по умолчанию в параметрах функции.

function read_file(file, delete_after = false) {
    #code
}

В этом примере Edge выдаст ошибку "Ожидание" ) "

Чтобы обойти это использование

function read_file(file, delete_after) {
  if(delete_after == undefined)
  {
    delete_after = false;
  }
  #code
}

По состоянию на 08 августа 2016 года это все еще проблема

3

ES6: Как уже упоминалось в большинстве ответов, в ES6 вы можете просто инициализировать параметр вместе со значением.


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

function foo (param1, param2) {
   param1 = arguments.length >= 1 ? param1 : "default1";
   param2 = arguments.length >= 2 ? param2 : "default2";
}
3
function helloWorld(name, symbol = '!!!') {
    name = name || 'worlds';
    console.log('hello ' + name + symbol);
}

helloWorld(); // hello worlds!!!

helloWorld('john'); // hello john!!!

helloWorld('john', '(>.<)'); // hello john(>.<)

helloWorld('john', undefined); // hello john!!!

helloWorld(undefined, undefined); // hello worlds!!!
3

В соответствии с синтаксисом

function [name]([param1[ = defaultValue1 ][, ..., paramN[ = defaultValueN ]]]) {
   statements
}

вы можете определить значение по умолчанию для формальных параметров. а также проверить значение undefined с помощью функции typeof.

2

Если вы используете ES6+ вы можете установить параметры по умолчанию следующим образом:

function test (foo = 1, bar = 2) {
  console.log(foo, bar);
}

test(5); // foo gets overwritten, bar remains default parameter

Если вам нужен синтаксис ES5 вы можете сделать это следующим образом:

function test(foo, bar) {
  foo = foo || 2;
  bar = bar || 0;
  
  console.log(foo, bar);
}

test(5); // foo gets overwritten, bar remains default parameter

В приведенном выше синтаксисе используется оператор OR. Оператор OR всегда возвращает первое значение, если оно может быть преобразовано в true если оно не возвращает значение righthandside. Когда функция вызывается без соответствующего аргумента, переменная параметра (bar в нашем примере) устанавливается undefined механизмом JS. undefined Затем преобразуется в значение false и, следовательно, оператор OR возвращает значение 0.

2

Используйте это, если вы хотите использовать последний синтаксис ECMA6:

function myFunction(someValue = "This is DEFAULT!") {
  console.log("someValue --> ", someValue);
}

myFunction("Not A default value") // calling the function without default value
myFunction()  // calling the function with default value

Он называется default function parameters. Он позволяет инициализировать формальные параметры со значениями по умолчанию, если не передано значение или неопределенный. ПРИМЕЧАНИЕ. Он не будет работать с Internet Explorer или более старыми браузерами.

Для максимально возможной совместимости используйте это:

function myFunction(someValue) {
  someValue = (someValue === undefined) ? "This is DEFAULT!" : someValue;
  console.log("someValue --> ", someValue);
}

myFunction("Not A default value") // calling the function without default value
myFunction()  // calling the function with default value

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

  • 0
    ПРИМЕЧАНИЕ: как говорит @BlackBeard, функция (param = value) НЕ БУДЕТ работать с IE. Используйте совместимую версию.
2

function throwIfNoValue() {
throw new Error('Missing argument');
}
function foo(argValue = throwIfNoValue()) {
return argValue ;
}

Здесь foo() - это функция, имеющая параметр argValue. Если мы не передадим что-либо в вызове функции здесь, тогда вызывается функция throwIfNoValue(), и возвращаемый результат будет присваиваться единственному аргументу argValue. Вот как вызов функции может использоваться как параметр по умолчанию. Это делает код более упрощенным и читаемым.

Этот пример был взят отсюда

1

Да, использование параметров по умолчанию полностью поддерживается в ES6:

function read_file(file, delete_after = false) {
  // Code
}

или же

const read_file = (file, delete_after = false) => {
    // Code
}

но до ES5 вы могли бы легко сделать это:

function read_file(file, delete_after) {
  var df = delete_after || false;
  // Code
}

Это означает, что если значение есть, используйте значение, в противном случае используйте второе значение после || операция, которая делает то же самое...

Примечание: также существует большая разница между этими значениями, если вы передадите значение в ES6 одно, даже если оно будет ложным, которое будет заменено новым значением, например, null или ""... но только одно ES5 будет заменено, если только переданное значение верно, потому что путь || за работой...

1

Если по каким - то причинам вы не на ES6 и используете lodash здесь является кратким способом по умолчанию параметров функции через _.defaultTo метод:

var fn = function(a, b) {
  a = _.defaultTo(a, 'Hi')
  b = _.defaultTo(b, 'Mom!')

  console.log(a, b)
}

fn()                 // Hi Mom!
fn(undefined, null)  // Hi Mom!
fn(NaN, NaN)         // Hi Mom!
fn(1)                // 1 "Mom!"
fn(null, 2)          // Hi 2
fn(false, false)     // false false
fn(0, 2)             // 0 2
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>

Который установит значение по умолчанию, если текущее значение равно NaN, null или undefined

0

Да, это называется параметром по умолчанию

Параметры функции по умолчанию позволяют инициализировать формальные параметры со значениями по умолчанию, если значение не определено или не определено.

Синтаксис:

function [name]([param1[ = defaultValue1 ][, ..., paramN[ = defaultValueN ]]]) {
   statements
}

Описание:

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

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

С параметрами по умолчанию в ES2015 проверка в теле функции больше не требуется. Теперь вы можете просто поместить значение по умолчанию в голову функции.

Пример различий:

// OLD METHOD
function multiply(a, b) {
  b = (typeof b !== 'undefined') ?  b : 1;
  return a * b;
}

multiply(5, 2); // 10
multiply(5, 1); // 5
multiply(5);    // 5


// NEW METHOD
function multiply(a, b = 1) {
  return a * b;
}

multiply(5, 2); // 10
multiply(5, 1); // 5
multiply(5);    // 5

Различные примеры синтаксиса:

Заполнение неопределенных значений других фальшивых значений:

Даже если значение задано явно при вызове, значение аргумента num является значением по умолчанию.

function test(num = 1) {
  console.log(typeof num);
}

test();          // 'number' (num is set to 1)
test(undefined); // 'number' (num is set to 1 too)

// test with other falsy values:
test('');        // 'string' (num is set to '')
test(null);      // 'object' (num is set to null)

Оценивается во время разговора:

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

function append(value, array = []) {
  array.push(value);
  return array;
}

append(1); //[1]
append(2); //[2], not [1, 2]


// This even applies to functions and variables
function callSomething(thing = something()) {
 return thing;
}

function something() {
  return 'sth';
}

callSomething();  //sth

Параметры по умолчанию доступны для более поздних параметров по умолчанию:

Парамеры, которые уже встречаются, доступны для более поздних параметров по умолчанию

function singularAutoPlural(singular, plural = singular + 's',
                        rallyingCry = plural + ' ATTACK!!!') {
  return [singular, plural, rallyingCry];
}

//["Gecko","Geckos", "Geckos ATTACK!!!"]
singularAutoPlural('Gecko');

//["Fox","Foxes", "Foxes ATTACK!!!"]
singularAutoPlural('Fox', 'Foxes');

//["Deer", "Deer", "Deer ... change."]
singularAutoPlural('Deer', 'Deer', 'Deer peaceably and respectfully \ petition the government for positive change.')

Функции, определенные внутри тела функции:

Представлен в Gecko 33 (Firefox 33/Thunderbird 33/SeaMonkey 2.30). Функции, объявленные в теле функции, не могут передаваться внутри параметров по умолчанию и бросать ReferenceError (в настоящее время TypeError в SpiderMonkey, см. Ошибку 1022967). Параметры по умолчанию всегда выполняются сначала, после чего декларации функций внутри тела функции оцениваются.

// Doesn't work! Throws ReferenceError.
function f(a = go()) {
  function go() { return ':P'; }
}

Параметры без умолчаний после параметров по умолчанию:

До Gecko 26 (Firefox 26/Thunderbird 26/SeaMonkey 2.23/Firefox OS 1.2) следующий код привел к SyntaxError. Это было исправлено в ошибке 777060 и работает как ожидается в более поздних версиях. Параметры по-прежнему заданы слева направо, переписывая параметры по умолчанию, даже если есть более поздние параметры без значений по умолчанию.

function f(x = 1, y) {
  return [x, y];
}

f(); // [1, undefined]
f(2); // [2, undefined]

Деструктурированный параметр с присвоением значения по умолчанию:

Вы можете использовать присвоение значений по умолчанию с помощью нотации назначения деструктурирования

function f([x, y] = [1, 2], {z: z} = {z: 3}) {
  return x + y + z;
}

f(); // 6
0
def read_file(file, delete_after = false)
  # code
end

Следующий код может работать в этой ситуации, включая ECMAScript 6 (ES6), а также более ранние версии.

function read_file(file, delete_after) {
    if(delete_after == undefined)
        delete_after = false;//default value

    console.log('delete_after =',delete_after);
}
read_file('text1.txt',true);
read_file('text2.txt');

поскольку значение по умолчанию в языках работает, когда значение параметра функции пропускается при вызове, в JavaScript ему присваивается неопределенное значение. Этот подход не выглядит привлекательно программно, но имеет обратную совместимость.

-3

Да, это будет работать в Javascript. Вы также можете сделать это:

function func(a=10,b=20)
{
    alert (a+' and '+b);
}

func(); // Result: 10 and 20

func(12); // Result: 12 and 20

func(22,25); // Result: 22 and 25

Ещё вопросы

Сообщество Overcoder
Наверх
Меню