有已知的原因为什么在提供ES6时将null作为参数传递给ES6而不使用默认参数?

function sayHello(name = "World") {
    console.log("Hello, " + name + "!");
}

sayHello("Jim");     // Hello, Jim!
sayHello(undefined); // Hello, World!
sayHello(null);      // Hello, null!

最佳答案

这不是那么明显

我已经阅读了有关undefinednull完全不同的原因的一些评论,这就是为什么它解释了默认参数的当前行为。

有人可能会争辩说,显式传递未定义的不应触发默认值替换,因为当我有一个函数时:

const f = (x = 'default') => console.log(x);

我希望以以下方式运行它时可以打印"default":
f();

但是当我明确将其运行为时,我希望它打印"undefined":
f(undefined);

因为否则我为什么首先要使用f(undefined)?显然,我的意图是提供一些论据而不是将其遗漏。

相反的例子

现在,考虑以下功能:
const g = (...a) => console.log(JSON.stringify(a));

当我将其用作:
g();

我得到:[]
但是当我将其用作:
g(undefined);

我得到:[null]
清楚地表明:

传递undefined
  • ,与不传递所有
  • 的参数不同
  • 有时null 可以是的默认值,而不是undefined

  • TC39决定

    可以在TC39于2012年7月24日的 session 记录中看到有关默认参数当前行为的一些背景信息:
  • https://github.com/rwaldron/tc39-notes/blob/master/es6/2012-07/july-24.md

  • 顺便说一句,它表明显式传递最初由传递的undefined并没有通过触发初稿中的默认值,并且正在讨论是否应该这样做。因此,您可以看到,对于TC39成员来说,当前的行为并不那么明显,而对于在此处发表评论的人们来说,现在似乎已经变得如此。

    其他语言

    话虽这么说,在一天结束时,决定什么触发和不触发默认值替换的决定完全是任意的。如果考虑一下,即使单独使用undefinednull也可能会很奇怪。某些语言只有undefined(例如Perl中的undef),有些语言只有null(例如Java),某些语言使用false的等效项或空列表或数组(例如Scheme,可以在其中使用空列表或#f(假)但是没有等效的null不同于空列表和错误值),有些语言甚至没有等效的nullfalseundefined(例如C使用整数而不是truefalse和NULL)指针,实际上是指向地址0的普通指针-即使通过任何测试空指针的代码进行映射,也无法访问该地址)。

    你可以做什么

    现在,我可以理解您需要用缺省值替换null了。不幸的是,这不是默认行为,但是您可以创建一个简单的函数来帮助您:
    const N = f => (...a) => f(...a.map(v => (v === null ? undefined : v)));
    

    现在,每次您要用默认值代替null值时,都可以像这样使用它。例如。如果您具有上述示例之一中的此功能:
    const f = (x = 'default') => console.log(x);
    

    它将为"default"f()打印f(undefined),但不为f(null)打印。但是,当您使用上面定义的N函数来定义f函数时,如下所示:
    const f = N((x = 'default') => console.log(x));
    

    现在,f()f(undefined)以及f(null)也会打印"default"

    如果您想要一些不同的行为,例如用默认值替换空字符串-对于有时可以设置为空字符串而不是不存在的环境变量很有用,您可以使用:
    const N = f => (...a) => f(...a.map(v => (v === '' ? undefined : v)));
    

    如果要替换所有伪造的值,可以这样使用:
    const N = f => (...a) => f(...a.map(v => (v || undefined)));
    

    如果要替换空对象,可以使用:
    const N = f => (...a) => f(...a.map(v => (Object.keys(v).length ? v : undefined)));
    

    等等...

    结论

    关键是它是您的代码,并且您知道函数的API应该是什么以及默认值应如何工作。幸运的是,JavaScript功能强大,足以让您使用一些高阶函数魔术轻松实现所需的功能(即使这不是默认值的默认行为)。

    07-24 09:46
    查看更多