设置JavaScript函数的默认参数值

时间:2009-05-21 20:07:18

标签: javascript function parameters default-parameters

我希望JavaScript函数具有可选参数,我将其设置为默认值,如果未定义该值则使用该参数(如果传递该值则忽略该值)。在Ruby中你可以这样做:

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

这是否适用于JavaScript?

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

29 个答案:

答案 0 :(得分:3129)

ES6/ES2015开始,默认参数在语言规范中。

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

正常工作。

参考:Default Parameters - MDN

  

如果传递无值未定义,默认函数参数允许使用默认值初始化形式参数。

您还可以simulate default named parameters via destructuring

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

答案 1 :(得分:582)

function read_file(file, delete_after) {
    delete_after = delete_after || "my default here";
    //rest of code
}

如果delete_after不是 falsey 值,则会将delete_after分配给"my default here",否则会分配字符串false。有关更多详细信息,请查看Doug Crockford's survey of the language and check out the section on Operators

如果您想传入 falsey 值,即nullundefined0""或{ {1}}。如果您需要传递 falsey 值,则需要使用Tom Ritter's answer中的方法。

当处理函数的许多参数时,允许使用者在对象中传递参数参数然后合并这些值与包含默认值的对象通常很有用用于功能

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

答案 2 :(得分:144)

我发现像这样简单的东西更加简洁和个性化。

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

function myFunc(x) {
  x = pick(x, 'my default');
} 

答案 3 :(得分:60)

在ECMAScript 6中,您实际上可以准确地写出您拥有的内容:

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

这会将delete_after设置为false(如果不存在)或undefined。您今天可以使用像这样的ES6功能,例如Babel

等转录器

See the MDN article for more information

答案 4 :(得分:25)

默认参数值

使用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;它们可以是任何有效的表达式,甚至是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

正如您所看到的,默认值表达式是延迟计算的,这意味着它们只在需要时才运行 - 也就是说,当参数的参数被省略或未定义时。

默认值表达式甚至可以是内联函数表达式调用 - 通常称为立即调用的函数表达式(IIFE)

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

答案 5 :(得分:11)

该解决方案适用于js:

a<- "19260701"
library(lubridate)
ymd(a)
[1] "1926-07-01 UTC"

答案 6 :(得分:9)

只需使用未定义的显式比较。

UPDATE timsheetdb.calendar 
SET    LoginDate = DATE_ADD('2016-02-29', INTERVAL 1 YEAR),
       LoginDay = DAYNAME(LoginDate = DATE_ADD('2016-02-29', INTERVAL 1 YEAR))

答案 7 :(得分:7)

作为更新...使用ECMAScript 6,您可以 FINALLY 在函数参数声明中设置默认值,如下所示:

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

f(1) === 50

由 - http://es6-features.org/#DefaultParameterValues

引用

答案 8 :(得分:7)

作为一名长期的C ++开发人员(Rookie to web development :)),当我第一次遇到这种情况时,我在函数定义中进行了参数赋值,就像在问题中提到的那样,如下所示。

function myfunc(a,b=10)

但请注意,它不能跨浏览器一致地工作。对我来说,它在我的桌面上使用chrome,但在android上没有使用chrome。 如上所述,更安全的选择是 -

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

这个答案的意图不是重复相同的解决方案,而是其他人已经提到的,但是要告知函数定义中的参数赋值可能适用于某些浏览器,但不依赖它。

答案 9 :(得分:7)

我强烈建议在javascript中使用默认参数值时要格外小心。当与forEachmapreduce等高阶函数结合使用时,它通常会产生错误。例如,请考虑以下代码行:

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

parseInt有一个可选的第二个参数function parseInt(s, [ radix =10]),但是使用三个参数映射调用parseInt :( element ,< em> index 和 array )。

我建议您将所需参数从可选/默认值参数中分离出来。如果您的函数需要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);

运行上面的代码片段说明了未使用参数的默认参数值背后隐藏的危险。

答案 10 :(得分:6)

对于有兴趣在Microsoft Edge中使用代码工作的任何人,请不要在函数参数中使用默认值。

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

在该示例中,Edge会抛出错误&#34;期待&#39;)&#39;&#34;&#39;

绕过这个用途

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

截至2016年8月8日,这仍是一个问题

答案 11 :(得分:3)

ES6:正如大多数答案中已经提到的那样,在ES6中,您可以简单地将参数和值一起初始化。


ES5:大多数给出的答案对我来说都不足够,因为在某些情况下,我可能不得不传递虚假的值,例如0nullundefined到一个功能。要确定参数是否未定义,因为那是我传递的值,而不是因为根本没有定义,所以我未定义:

function foo (param1, param2) {
   param1 = arguments.length >= 1 ? param1 : "default1";
   param2 = arguments.length >= 2 ? param2 : "default2";
}

答案 12 :(得分:3)

根据语法

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

您可以定义形式参数的默认值。 并使用 typeof 函数检查未定义的值。

答案 13 :(得分: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!!!

答案 14 :(得分:3)

如果要使用最新的 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

答案 15 :(得分:2)

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

此处foo()是一个函数,其参数名为argValue。如果我们在此处的函数调用中未传递任何内容,则将调用函数throwIfNoValue()并将返回的结果分配给唯一的参数argValue。这就是将函数调用用作默认参数的方式。这使代码更加简化和可读。

This example has been taken from here

答案 16 :(得分: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,则始终返回第一个值,否则不能返回右侧的值。在没有相应参数的情况下调用该函数时,JS引擎会将参数变量(在我们的示例中为bar)设置为undefinedundefined然后转换为false,因此OR运算符返回值0。

答案 17 :(得分:1)

如果由于某种原因您未使用lodash在ES6上不是并且 ,这是通过_.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 未定义

,则会设置默认值

答案 18 :(得分: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 仅在传递的值是真实的情况下才会被替换,这是因为||的工作方式...

答案 19 :(得分:1)

我注意到一些答案提到使用默认参数不能移植到其他浏览器,但公平地指出你可以使用像 Babel 这样的转译器将你的代码转换为 ES5 语法,用于支持有限的浏览器用于现代 JS 功能。

所以:

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

将被转译为(在 Babel REPL 中尝试 -> https://babeljs.io/repl/):

"use strict";

function read_file(file) {

  var delete_after =
    arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
  
  //Code...

}

当然,如果您不打算使用转译,那么像其他人演示的那样在函数体中设置默认参数也完全没问题。

答案 20 :(得分: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中,它将分配给 undefined 。这种方法在程序上看起来并不吸引人,但具有向后兼容性

答案 21 :(得分:0)

是的,这被称为默认参数

默认函数参数允许在未传递任何值或未定义的情况下使用默认值初始化形式参数。

语法:

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

说明:

函数的参数默认为undefined但是,在某些情况下,设置其他默认值可能很有用。这是默认参数可以提供帮助的地方。

过去,设置默认值的一般策略是在函数的主体中测试参数值,如果未定义,则分配一个值。如果调用中未提供任何值,则其值将不确定。您必须设置条件检查,以确保该参数未定义

使用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(当前在SpiderMonkey中为TypeError,请参见bug 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

答案 22 :(得分:0)

设置默认参数的另一种方法是使用参数的对象映射,而不是直接使用参数。 例如,

const defaultConfig = {
 category: 'Animals',
 legs: 4
};

function checkOrganism(props) {
 const category = props.category || defaultConfig.category;
 const legs = props.legs || defaultConfig.legs;
}

这样,很容易扩展参数,而不必担心参数长度不匹配。

答案 23 :(得分:0)

答案是肯定的。实际上,有许多语言支持默认参数。 Python是其中之一:

def(a, enter="Hello"):
   print(a+enter)

尽管由于括号这是Python 3代码,但函数中的默认参数在JS中也适用。

例如,在您的情况下:

function read_file(file, deleteAfter=false){
  console.log(deleteAfter);
}

read_file("test.txt");

但是有时候您确实不需要默认参数。

您可以在函数启动后立即定义变量,如下所示:

function read_file(file){
  var deleteAfter = false;
  console.log(deleteAfter);
}

read_file("test.txt");

在我的两个示例中,它都返回相同的内容。但是有时它们实际上可能有用,例如在非常高级的项目中。

因此,总而言之,可以在JS中使用默认参数值。但这几乎与在函数启动后立即定义变量相同。但是,有时它们仍然非常有用。您可能已经注意到,默认参数值比标准函数少花1行代码,而标准方法是在函数启动后立即定义参数。

答案 24 :(得分:0)

未来之声

将来,您将能够将一个对象“传播”到另一个对象(当前截至2019年NOT supported by Edge!)-演示如何使用该对象作为美观的默认选项,而与顺序无关:

function test(options) {
    var options = {
       // defaults
       url: 'defaultURL',
       some: 'somethingDefault',
       // override with input options
       ...options
    };
    
    var body = document.getElementsByTagName('body')[0];
    body.innerHTML += '<br>' + options.url + ' : ' + options.some;
}
test();
test({});
test({url:'myURL'});
test({some:'somethingOfMine'});
test({url:'overrideURL', some:'andSomething'});
test({url:'overrideURL', some:'andSomething', extra:'noProblem'});

MDN参考:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax

...与此同时Edge DOES support is Object.assign()(IE不会,但我真的希望我们可以将IE留在后面:))

类似地,您可以做到

    function test(options) {
        var options = Object.assign({
           // defaults
           url: 'defaultURL',
           some: 'somethingDefault',
        }, options); // override with input options
        
        var body = document.getElementsByTagName('body')[0];
        body.innerHTML += '<br>' + options.url + ' : ' + options.some;
    }
    test();
    test({});
    test({url:'myURL'});
    test({some:'somethingOfMine'});
    test({url:'overrideURL', some:'andSomething'});
    test({url:'overrideURL', some:'andSomething', extra:'noProblem'});

编辑:由于对const选项的评论-在功能其余部分中使用常量选项的问题实际上不是,您不能这样做只是因为您不能在其自己的声明中使用常量变量-您必须将输入命名调整为

function test(input_options){
   const options = {
     // defaults
     someKey:    'someDefaultValue',
     anotherKey: 'anotherDefaultValue',

     // merge-in input options
     ...input_options
   };

   // from now on use options with no problem
}

答案 25 :(得分:0)

是-证明:

function read_file(file, delete_after = false) {
  // Code
  console.log({file,delete_after});
}



// TEST
read_file("A");
read_file("B",true);
read_file("C",false);

答案 26 :(得分:0)

export const getfilesize = (bytes, decimals = 2) => {
    if (bytes === 0){ 
        return '0 Bytes';
    }else{
        const k = 1024;
        const dm = decimals < 0 ? 0 : decimals;
        const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
        const i = Math.floor(Math.log(bytes) / Math.log(k));
        return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];

    }
}

答案 27 :(得分:-1)

也只是为了展示我的技能(笑),即使没有如下命名参数,也可以编写以上函数:

ES5及更高版本

function foo() {
    a = typeof arguments[0] !== 'undefined' ? a : 42;
    b = typeof arguments[1] !== 'undefined' ? b : 'default_b';
    ...
}

ES6及更高版本

function foo(...rest) {
    a = typeof rest[0] !== 'undefined' ? a : 42;
    b = typeof rest[1] !== 'undefined' ? b : 'default_b';
    ...
}

答案 28 :(得分:-3)

是的,这可以在Javascript中使用。你也可以这样做:

Count()