我发现c#中的命名参数特性在某些情况下非常有用。

calculateBMI(70, height: 175);

如果我想在JavaScript中使用这个,我可以使用什么?


我不想要的是:

myFunction({ param1: 70, param2: 175 });

function myFunction(params){
  // Check if params is an object
  // Check if the parameters I need are non-null
  // Blah blah
}

这个方法我已经用过了。还有别的办法吗?

我可以使用任何库来做到这一点。


当前回答

NB。正如评论中提到的,我2016年的答案是不正确的,具有误导性。

尝试Node-6.4.0 (process.versions. Node-6.4.0)。v8 = '5.0.71.60')和Node Chakracore-v7.0.0-pre8,然后是Chrome-52 (v8 =5.2.361.49),我注意到命名参数几乎是实现的,但顺序仍然优先。我找不到ECMA标准是怎么说的。

>function f(a=1, b=2){ console.log(`a=${a} + b=${b} = ${a+b}`) }

> f()
a=1 + b=2 = 3
> f(a=5)
a=5 + b=2 = 7
> f(a=7, b=10)
a=7 + b=10 = 17

但是必须遵守秩序!!这是标准行为吗?

> f(b=10)
a=10 + b=2 = 12

其他回答

与通常认为的相反,命名参数可以在标准的旧式JavaScript中(仅用于布尔参数)通过简单、整洁的编码约定实现,如下所示。

function f(p1=true, p2=false) {
    ...
}

f(!!"p1"==false, !!"p2"==true); // call f(p1=false, p2=true)

警告:

必须保留参数的顺序——但这种模式仍然有用,因为它可以很明显地显示哪个实际参数对应哪个形式参数,而不必为函数签名进行grep或使用IDE。 这只适用于布尔值。但是,我相信可以使用JavaScript独特的类型强制语义为其他类型开发类似的模式。

NB。正如评论中提到的,我2016年的答案是不正确的,具有误导性。

尝试Node-6.4.0 (process.versions. Node-6.4.0)。v8 = '5.0.71.60')和Node Chakracore-v7.0.0-pre8,然后是Chrome-52 (v8 =5.2.361.49),我注意到命名参数几乎是实现的,但顺序仍然优先。我找不到ECMA标准是怎么说的。

>function f(a=1, b=2){ console.log(`a=${a} + b=${b} = ${a+b}`) }

> f()
a=1 + b=2 = 3
> f(a=5)
a=5 + b=2 = 7
> f(a=7, b=10)
a=7 + b=10 = 17

但是必须遵守秩序!!这是标准行为吗?

> f(b=10)
a=10 + b=2 = 12

这确实是伪代码,但我相信它会起作用(我知道它在TypeScript中起作用;我将它用于JavaScript)。

// Target Function
const myFunc = (a=1,b=2,c=3) => {a+b+c}

// Goal usage:
myFunc(a=5, b=6) // 14
myFunc(c=0) // 3

// Set your defaults
const myFuncDefaults = {a:1, b:2, c:3};

// Override them with passed parameters
const myFuncParams = (params) => { return Object.assign(myFuncDefaults, params)}


// Use the overloaded dict as the input
const myFunc2 = (params) => {
  let {a, b, c} = myFuncParams(params);
  return myFunc(a, b, c)
}

// Usage:
myFunc({a:5, b:6}) // 14
myFunc({c:0}) // 3

// Written more succinctly:
const myFunc = (params) => {
  let {a,b,c} = Object.assign({a:1, b:2, c:3}, params)
  return a + b + c
}

不管它的价值是什么,TypeScript通过提示来实现这一点:

interface IParams {
  a: number;
  b: number;
  c: number;
}

const myFunc = (params: Partial<IParams>): number => {
  const default: IParams = {a:1, b:2, c:3};
  let {a, b, c} = Object.assign(default, params)
  return a + b + c
}

还有另一种方法。如果通过引用传递对象,则该对象的属性将出现在函数的局部作用域中。我知道这适用于Safari(还没有检查其他浏览器),我不知道这个功能是否有名字,但下面的例子说明了它的用法。

尽管在实践中,我不认为这在您已经使用的技术之外提供了任何功能价值,但它在语义上更简洁一些。它仍然需要传递一个对象引用或一个对象字面量。

function sum({ a:a, b:b}) {
    console.log(a+'+'+b);
    if(a==undefined) a=0;
    if(b==undefined) b=0;
    return (a+b);
}

// will work (returns 9 and 3 respectively)
console.log(sum({a:4,b:5}));
console.log(sum({a:3}));

// will not work (returns 0)
console.log(sum(4,5));
console.log(sum(4));

如果你想弄清楚每个参数是什么,而不仅仅是调用

someFunction(70, 115);

做以下几点:

var width = 70, height = 115;
someFunction(width, height);

当然,这是额外的一行代码,但它在可读性上更胜一筹。