为JavaScript函数设置默认参数值

2651

我想要一个JavaScript函数可以有可选参数,并且可以设置默认值,如果该值未定义则使用默认值(如果传递了值,则忽略默认值)。在Ruby中,您可以这样做:

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

这个JavaScript代码可以运行吗?

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

2
ES6 开始,这将起作用:function read_file(file, delete_after=false){}; - Azhar Uddin Sheikh
29个回答

8

如果您希望代码在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
}

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

7

如果您正在使用 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运算符。如果可以将第一个值转换为true,则OR运算符始终返回第一个值,否则返回右侧的值。当没有相应的参数调用函数时,JS引擎会将参数变量(在我们的示例中为bar)设置为undefined。 undefined然后被转换为false,因此OR运算符返回值0。

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

6

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


ES5: 大多数给出的答案对我来说都不够好,因为有时我可能需要传递 0nullundefined 等假值到函数中。为了判断参数是否是未定义的,因为这是我所传递的值而不是由于根本没有被定义而导致的未定义,我会这样做:

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

6

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

它被称为默认函数参数。如果未传递任何值或未定义变量,则允许使用默认值来初始化形式参数。 注意:它不适用于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”。

1
注意:正如@BlackBeard所说,function(param=value)在IE中不起作用。请使用兼容版本。 - MagicLAMP

5

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

这里的foo()是一个带有参数argValue的函数。如果在函数调用中没有传递任何参数,那么函数throwIfNoValue()将被调用,并将返回结果分配给唯一的参数argValue。这就是如何使用函数调用作为默认参数。这使得代码更简化和易读。

此示例摘自此处


5
根据语法,如下所示:
function [name]([param1[ = defaultValue1 ][, ..., paramN[ = defaultValueN ]]]) {
   statements
}

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

5

是的,在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 的函数,即使该值为 falsy,也会被替换为新值,例如 null"" ... 但是 ES5 的函数仅在传递的值为 truthy 时才会被替换,这是因为 || 的工作方式不同...

4
如果你不在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>

如果当前值为 NaNnullundefined,则会设置默认值。

4

未来的声音

在未来,你将能够将一个物体“传播”到另一个物体(截至2019年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/zh-CN/docs/Web/JavaScript/Reference/Operators/Spread_syntax

...同时,Edge支持的是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
}

问题在于通常情况下你不想这样做,因为这会重新分配已经定义的选项,但你可以将其与其他变量一起使用,这是合法的。 - frank-dspeed
函数测试(选项){ /如果您现在使用const options = {},它将抛出错误/ } - frank-dspeed
当您创建一个函数并将名称选项作为参数传递时,请勿使用全局变量。在函数内部,选项被定义在函数(opt){}中。opt被定义,您不能在该函数内部使用const opt。如果经常这样做并且看起来像您的一般模式,则会导致变量重新赋值,这是不好的。这是一个问题。 - frank-dspeed
@Google-Frank-Dspeed,你的意思是说你不能这样写 function(opt){ const opt = /*some merging*/; } 吗?那肯定行不通,因为你会在变量声明之前使用 const 变量 - 你需要调整一下 - function test(input_opt){ const opt = { someKey: 'someDefaultValue', ...input_opt} } - jave.web
1
@Google-Frank-Dspeed,不过更多新手可能会对此感到困惑,所以我已经添加了如何编辑的代码:) 所以感谢您为其他人指出这一点:) - jave.web

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接