题 设置JavaScript函数的默认参数值


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

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

这适用于JavaScript吗?

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

2022
2018-05-21 20:07


起源




答案:


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

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

只是工作。

参考: 默认参数 - MDN

默认函数参数允许使用默认值初始化形式参数if 没有价值 要么 未定义 通过。

你也可以 模拟默认值 命名 参数通过解构

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

预ES2015

有很多方法,但这是我首选的方法 - 它可以让你传递任何你想要的东西,包括false或null。 (typeof null == "object"

function foo(a, b) {
  a = typeof a !== 'undefined' ? a : 42;
  b = typeof b !== 'undefined' ? b : 'default_b';
  ...
}

2937
2018-05-21 20:10



您也可以将其封装为: function defaultFor(arg, val) { return typeof arg !== 'undefined' ? arg : val; } 然后你可以称之为 a = defaultFor(a, 42); - Camilo Martin
@SiPlus,您在尝试使用时免费获得额外的参考错误 undefined 对象:p即使它可能适用于某些浏览器并且可能更快, null 仍然是一个对象和 undefined 是指原始类型,它试图告诉我这里什么都没有,甚至没有 null。请看这里,两个案例简而言之: 的JavaScript /参考/ Global_Objects /未定义。 - Sampo Sarrala
如果你检查一个对象的属性,那么 typeof 是多余的。 function foo(data) { var bar = data.bar !== undefined ? data.bar : 'default'; } 这不会引发参考错误并且简洁。 - Dziamid
我知道这很小,但我不喜欢你的分配方式 a = a 和 b = b 当这些参数未定义时。此外,具有复杂条件的三元运算符可能难以为将来的维护者阅读。我更喜欢以下语法: if (typeof a == 'undefined') a = 42  - 没有不必要的任务加上更容易阅读。 - Daddy32
有没有理由使用 typeof?这样做似乎更简单 a === undefined。加上这种方式,如果拼写错误,你会收到参考错误 undefined 与把它放在一个字符串中。 - Abe Voelker


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

这是指定的 delete_after 的价值 delete_after 如果不是 falsey 值,否则它分配字符串 "my default here"。有关更多详细信息,请查看 Doug Crockford对该语言的调查,并查看运算符部分

如果你想传入一个,这种方法不起作用 falsey 价值即 falsenullundefined0 要么 ""。如果您需要 falsey 要传递的值需要使用方法 汤姆里特的答案

在处理函数的许多参数时,允许使用者在对象中传递参数参数然后通常是有用的 合并 这些值包含一个包含函数默认值的对象

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

559
2018-05-21 20:09



我发现这个不足,因为我可能想要传递虚假。 - Tom Ritter
我发现它适合大多数情况 - Russ Cam
这也不适用于0. :( - Alex Kahn
它不适用于任何虚假价值 - Russ Cam
因为它不适用于虚假值,它可能会造成维护噩梦。一些代码总是在之前通过了真正的值并且突然失败,因为在可用的更强大的方法的情况下应该避免传递假的。 - jinglesthula


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

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

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

137
2018-05-21 20:18



更新:如果您正在使用 underscore.js 已经发现它更好用了 _.defaults(iceCream, {flavor: "vanilla", sprinkles: "lots"});。许多人认为使用这个答案中显示的全局命名空间是一种不好的做法。您也可以考虑为这个常见任务滚动自己的实用程序(例如。 util.default(arg, "defaul value"))如果不想使用下划线,但我迟早会迟早使用下划线无论如何都没有重新发明轮子。 - andersand
@andersand我喜欢这样的想法 util.default(arg, "defaul value"))  你或@ tj111会发布快速演示吗? - JasonDavis
我实际推荐这个,我用它并称之为“por”,代表“参数或” - super
不要说typeof arg =='undefined',而是说arg === undefined - OsamaBinLogin
@OsamaBinLogin你说的对于当前的JS是正确的 - 旧的测试仍然存在,因为在某些浏览器上它曾经可以覆盖 undefined 与其他一些值,导致测试失败。 - Alnitak


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

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

这将设定 delete_after 至 false 如果它不存在或 undefined。你今天可以使用像这样的ES6功能,例如 巴别塔

有关更多信息,请参阅MDN文章


54
2018-05-29 15:25



ECMAScript 6我想......(我会自己纠正,但我不能编辑<6个字符) - Zac
等待浏览器获取ECMAScript 6 - Adriano Resende
巴贝尔会把这个转移到什么地方? - harryg
@harryg: babeljs.io/repl/... - Felix Kling
这是ES6的兼容性表 kangax.github.io/compat-table/es6/#default_function_parameters 不幸的是这种语法 尚不支持。 - freemanoid


默认参数值

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

18
2017-10-15 17:58





该解决方案适用于js:

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

8
2017-11-16 11:29



如果发生了什么 delete_after 是 0 要么 null?对于这些情况,它将无法正常工作。 - Dmitri Pavlutin
@StephanBijzitter在某些情况下才会出现这种情况。但是如果你只想要默认值来取消设置值,那么这不起作用,因为0或null!=== false。 - Rutrus
@Rutrus:我不明白你刚才说的话。 - Stephan Bijzitter
关于什么 delete_after = delete_after === undefined ? false : delete_after? - aashah7


只需使用与undefined的显式比较。

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

6
2017-11-16 07:34