有已知的原因为什么在提供ES6时将null
作为参数传递给ES6而不使用默认参数?
function sayHello(name = "World") {
console.log("Hello, " + name + "!");
}
sayHello("Jim"); // Hello, Jim!
sayHello(undefined); // Hello, World!
sayHello(null); // Hello, null!
最佳答案
这不是那么明显
我已经阅读了有关undefined
与null
完全不同的原因的一些评论,这就是为什么它解释了默认参数的当前行为。
有人可能会争辩说,显式传递未定义的不应触发默认值替换,因为当我有一个函数时:
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 记录中看到有关默认参数当前行为的一些背景信息:
顺便说一句,它表明显式传递最初由传递的
undefined
并没有通过触发初稿中的默认值,并且正在讨论是否应该这样做。因此,您可以看到,对于TC39成员来说,当前的行为并不那么明显,而对于在此处发表评论的人们来说,现在似乎已经变得如此。其他语言
话虽这么说,在一天结束时,决定什么触发和不触发默认值替换的决定完全是任意的。如果考虑一下,即使单独使用
undefined
和null
也可能会很奇怪。某些语言只有undefined
(例如Perl中的undef
),有些语言只有null
(例如Java),某些语言使用false
的等效项或空列表或数组(例如Scheme,可以在其中使用空列表或#f
(假)但是没有等效的null
不同于空列表和错误值),有些语言甚至没有等效的null
,false
或undefined
(例如C使用整数而不是true
和false
和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功能强大,足以让您使用一些高阶函数魔术轻松实现所需的功能(即使这不是默认值的默认行为)。