我发现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
}

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

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


当前回答

不——对象方法是JavaScript对此的答案。如果你的函数需要一个对象而不是单独的参数,这就没有问题。

其他回答

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

someFunction(70, 115);

做以下几点:

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

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

是的,嗯,有点。我找到了两个解决方案。我只解释一个。

在这个解决方案中,我们放弃了位置参数。

我们可以使用一个对象(几乎与Python中的dict相同)来传递参数。

在这个例子中,我使用函数来生成一个图像文件的名称:

// First we define our function with just ONE argument
function name_of_img(img_desc){

  // With this step, any undefined value will be assigned a value
  if(img_desc.size == undefined) {img_desc.size = "400x500"}
  if(img_desc.format == undefined) {img_desc.format = ".png"}

  console.log(img_desc.size + img_desc.format)
}

// Notice inside our function we're passing a dict/object

name_of_img({size: "200x250", format : ".jpg"})
// In Python name_of_img(size="200x250" , format="jpg")
// returns "200x250.jpg"

name_of_img({size: "1200x950"})
// In Python name_of_img(size="1200x950")
// returns "1200x950.png"

我们可以修改这个例子,所以我们也可以使用位置参数,我们也可以修改它,所以非有效参数可以传递,我想我会做一个关于这个的GitHub存储库。

不——对象方法是JavaScript对此的答案。如果你的函数需要一个对象而不是单独的参数,这就没有问题。

这确实是伪代码,但我相信它会起作用(我知道它在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
}

很多人说使用“传递对象”技巧,这样你就有了命名参数。

/**
 * My Function
 *
 * @param {Object} arg1 Named arguments
 */
function myFunc(arg1) { }

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

这很有效,除了…当涉及到大多数IDE时,我们很多开发人员依赖于IDE中的类型/参数提示。我个人使用PhpStorm(以及其他JetBrains ide,如Python的PyCharm和Objective-C的AppCode)。

使用“传递对象”技巧的最大问题是,当你调用函数时,IDE会给你一个单一的类型提示,仅此而已……我们怎么知道什么参数和类型应该进入arg1对象?

所以…“传递一个对象”的把戏对我没用……实际上,在我知道函数需要什么参数....之前,不得不查看每个函数的文档块,这导致了更令人头痛的问题当然,这对于维护现有代码非常有用,但对于编写新代码则非常糟糕。

这就是我使用的技巧…现在,它可能会有一些问题,一些开发人员可能会告诉我我做错了,当涉及到这些事情时,我有一个开放的心态……我总是愿意寻找更好的方法来完成一项任务。因此,如果这种技术有问题,欢迎发表评论。

/**
 * My Function
 *
 * @param {string} arg1 Argument 1
 * @param {string} arg2 Argument 2
 */
function myFunc(arg1, arg2) { }

var arg1, arg2;
myFunc(arg1='Param1', arg2='Param2');

This way, I have the best of both worlds. New code is easy to write as my IDE gives me all the proper argument hints. And, while maintaining code later on, I can see at a glance, not only the value passed to the function, but also the name of the argument. The only overhead I see is declaring your argument names as local variables to keep from polluting the global namespace. Sure, it's a bit of extra typing, but it's trivial compared to the time it takes to look up docblocks while writing new code or maintaining existing code.

更新- 2022年

JavaScript现在可以在ES6中使用对象解构来实现类似于命名参数的功能。大多数较新的浏览器都可以使用此功能,请参阅浏览器支持

它是这样工作的:


// Define your function like this
function myFunc({arg1, arg2, arg3}) {
    // Function body
}

// Call your function like this
myFunc({arg1: "value1", arg2: "value2", arg3: "value3"})

// You can also have default values for arguments
function myFunc2({firstName, lastName, age = 21}) {
    // Function body
}

// And you can call it with or without an "age" argument
myFunc({firstName: "John", lastName: "Doe"}) // Age will be 21
myFunc({firstName: "Jane", lastName: "Doe", age: 22})

最好的部分是现在大多数IDE都支持这种语法,并且您可以获得良好的参数提示支持

打印稿

对于那些使用TypeScript的人,你可以使用这个语法做同样的事情

function myFunc(
    {firstName, lastName, age = 21}:
    {firstName: string, lastName: string, age?: number}
) {
    // Function body
}

或者,使用接口

interface Params {
    firstName: string
    lastName: string
    age?: number
}

function myFunc({firstName, lastName, age = 21}: Params) {
    // Function body
}