在ES6中作为参数传递NULL时,在提供一个参数时不使用默认参数

时间:2015-09-22 19:13:07

标签: javascript ecmascript-6 optional-parameters

是否有一个已知的原因,为什么在提供一个参数时,传入null作为参数在ES6中不使用默认参数?

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

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

4 个答案:

答案 0 :(得分:28)

这就是规范中如何定义默认参数。见MDN :(强调我的)

  

如果没有值或未定义,则默认函数参数允许使用默认值初始化形式参数。

null既不是没有值,也不是undefined,因此它不会触发默认初始化。

答案 1 :(得分:22)

这不是那么明显

我已经阅读了为什么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]

清楚地表明:

  1. 传递undefined 不一样,因为根本没有传递参数
  2. 有时null 可以是默认值而不是undefined
  3. TC39决定

    有关默认参数当前行为的一些背景信息可以在TC39的2012年7月24日会议记录中看到:

    顺便提一下,它显示明确传递undefined原来没有触发初稿中的默认值,并且讨论了它是否应该这样做。因此,您可以看到TC39成员目前的行为并不那么明显,因为现在似乎是在这里发表评论的人。

    其他语言

    有人说过,在一天结束时,应该和不应该触发默认值替换的决定完全是任意的。即使有一个单独的undefinednull,如果你考虑它也可能会非常奇怪。某些语言只有undefined(如Perl中的undef),有些语言只有null(如Java),有些语言使用等效的false或空列表或数组那个(比如你可以有一个空列表或#f(假)的方案,但没有等同于null的空列表和虚假值)和某些语言不同t甚至等价nullfalseundefined(比如使用整数而不是truefalse的C和一个实际上是正常的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)));
    

    如果您想要替换空对象,可以使用:

    {{1}}

    依旧......

    结论

    关键是它是你的代码,你知道你的函数的API应该是什么以及默认值应该如何工作。幸运的是,JavaScript足够强大,可以让你轻松地实现你所需要的东西(即使这不是默认值的默认行为,可以这么说),具有一些更高阶函数的魔力。

答案 2 :(得分:1)

null是一个不会触发默认值的值,当参数为undefined时将使用默认值。

答案 3 :(得分:0)

ramdajs 版本代码

// import ramda

// infra code
const isEmptyOrNil = (value) => isEmpty(value) || isNil(value)
const nullChange = (defaultValue) => (value) => isEmptyOrNil(value)? defaultValue: value

// single null
const _somef = (value) => value
const somefWithDefault = (defaultValue) => pipe(nullChange(defaultValue), _somef)
const somef = somefWithDefault('myValue')

somef(null)

// many args
const _somef2 = (value, value2, value3) => value + value2 + value3
const nullChangeMyValue = nullChange('myValue')
const somef2 = useWith(_somef2, [nullChangeMyValue, nullChangeMyValue, nullChangeMyValue])

somef2(null, undefined, 1234)

// many args2 version2
const nullChangeWith = (defaultValue) => nullChange(defaultValue)
const arrayNullChangeWith = (defaultValue) => (array) => array.map(nullChangeWith(defaultValue))
const arg2Array = (...args) => args
const funcApplyDefaultValue = (defaultValue) => (func) => pipe(
  arg2Array, arrayNullChangeWith(defaultValue), apply(func)
)

const v2somef2 = funcApplyDefaultValue(8)(_somef2)

v2somef2(1,2,null)

混帐:https://gist.github.com/otwm/3a6358e53ca794cc2e57ade4af91d3bb