【问题标题】:Splat operators in JavaScript, equivalent to *args and **kwargs in Python?JavaScript 中的 Splat 运算符,相当于 Python 中的 *args 和 **kwargs?
【发布时间】:2013-06-27 03:33:34
【问题描述】:

我经常使用 Python,而且我现在正在快速学习 JavaScript(或者我应该说重新学习)。所以,我想问一下,JavaScript中*args**kwargs的等价物是什么?

【问题讨论】:

  • coffeescript 有splats
  • 尝试拨打function.apply(obj, [args])。每个函数对象都有一个apply() 方法,该方法使用上下文(即obj)和参数数组调用函数。
  • 为什么不直接传入一个键值对对象呢?您可以在 javascript 中执行 if (key in obj),就像在 python 中执行 if arg in kwargs 一样。然后,如果它返回 true,您可以使用 obj[key] 获取值。

标签: javascript python


【解决方案1】:

*args 最接近的成语是

function func (a, b /*, *args*/) {
    var star_args = Array.prototype.slice.call (arguments, func.length);
    /* now star_args[0] is the first undeclared argument */
}

利用Function.length 是函数定义中给出的参数数量这一事实。

你可以把它打包成一个小助手例程,比如

function get_star_args (func, args) {
    return Array.prototype.slice.call (args, func.length);
}

然后做

function func (a, b /*, *args*/) {
    var star_args = get_star_args (func, arguments);
    /* now star_args[0] is the first undeclared argument */
}

如果您想使用语法糖,请编写一个函数,将一个函数转换为另一个使用必需和可选参数调用的函数,并将所需参数以及任何其他可选参数作为数组传递给 final位置:

function argsify(fn){
    return function(){
        var args_in   = Array.prototype.slice.call (arguments); //args called with
        var required  = args_in.slice (0,fn.length-1);     //take first n   
        var optional  = args_in.slice (fn.length-1);       //take remaining optional
        var args_out  = required;                          //args to call with
        args_out.push (optional);                          //with optionals as array
        return fn.apply (0, args_out);
    };
}

如下使用:

// original function
function myfunc (a, b, star_args) {
     console.log (a, b, star_args[0]); // will display 1, 2, 3
}

// argsify it
var argsified_myfunc = argsify (myfunc);

// call argsified function
argsified_myfunc (1, 2, 3);

再一次,如果你愿意让调用者将可选参数作为数组传递,你可以跳过所有这些笨拙的东西:

myfunc (1, 2, [3]);

**kwargs 确实没有类似的解决方案,因为 JS 没有关键字参数。相反,只需要求调用者将可选参数作为对象传递:

function myfunc (a, b, starstar_kwargs) {
    console.log (a, b, starstar_kwargs.x);
}

myfunc (1, 2, {x:3});

ES6 更新

为了完整起见,让我补充一点,ES6 用剩余参数特性解决了这个问题。见Javascript - '...' meaning

【讨论】:

  • 直接研究 CoffeeScript 比花时间使用 javascript 更容易吗?
  • 这让我想起有人问我是否应该直接进入 FORTRAN 而不是花时间在 7090 汇编器上。当然,CoffeeScript 是一个很好的方法。或者 TypeScript 或 Traceur,它为您提供了到 ECMAScript 6 的迁移路径(顺便说一下,其中的语法是 function (a, ...optionals))。其中任何一个还为您提供默认参数值,而您无需使用与我的答案中相同的一些想法使用 POJS 一起破解它。
  • ES6 链接 404 未找到
【解决方案2】:

ES6 为 JavaScript 添加了扩展运算符。

function choose(choice, ...availableChoices) {
    return availableChoices[choice];
}

choose(2, "one", "two", "three", "four");
// returns "three"

【讨论】:

  • 很遗憾这只是类似于*args,不能解压像**kwargs这样的对象
  • 类似的解压对象的方法是function choose({choice, ...availableChoices}) {/*...*/}。用法是:choose({choice: 'a', a: 1, b: 2, c: 3});
  • 该评论确实属于答案
  • 有人可以指出一个在@eskimwier 的评论中详细介绍的资源吗?
  • @Haniver,不确定资源,但我在我的网站上发了一篇关于它的快速帖子:mike.distro.work/…
【解决方案3】:

我在这里找到了一个很好的解决方案: http://readystate4.com/2008/08/17/javascript-argument-unpacking-converting-an-array-into-a-list-of-arguments/

基本上,使用function.apply(obj, [args]) 而不是function.call。 apply 将数组作为第二个参数并为您“splats”它。

【讨论】:

  • 当我想将函数和参数传递给回调时,这对我有用。
【解决方案4】:

最接近的等价物是arguments pseudo-array

【讨论】:

    【解决方案5】:

    ECMAScript 6 将具有 rest parameters,它与 splat 运算符执行相同的操作。

    【讨论】:

      【解决方案6】:

      对于那些可能对 *args 和 **kwargs 魔法变量有点迷茫的人,请阅读http://book.pythontips.com/en/latest/args_and_kwargs.html

      总结: *args 和 **kwargs 只是编写魔法变量的常规方法。您可以只说 * 和 ** 或 *var 和 **vars。也就是说,让我们谈谈 2019 年的 JavaScript 等价物。

      *args 在 python 中表示一个 JavaScript 数组,例如["one", "two", "three"] 将其传递给 python 函数,您只需将该函数定义为 def function_name(*args):这意味着该函数接受“数组”或“如果你愿意”来调用您只需使用函数 function_name(["one", "two", "three"]):

      在 JavaScript 中也可以使用 :

      function func(x,y,z){
        ...
      }
      let args = ["one", "two", "three"];
      
      func(...args)
      
      **or more dynamically as**
      
       function func(inputs<T>:Array){
      
         for(index in inputs){
      
            console.log(inputs[index]);
         }
      }
      let args = ["one", "two", "three"];
      
      func(args)
      

      看看https://codeburst.io/a-simple-guide-to-destructuring-and-es6-spread-operator-e02212af5831

      另一方面,

      **kwargs 仅表示键值对(对象)的数组,仅此而已。因此 **kwargs 例如是 [{"length": 1, "height": 2}, {"length":3, "height": 4}]

      在python中定义一个接受对象数组的函数,你只需说 def function_name(**kwargs): 然后调用你可以做 function_name( [{"length": 1, "height": 2}, {"长度”:3,“高度”:4}]):

      在 JS 中类似

      const kwargs = [{"length": 1, "height": 2}, {"length":3, "height": 4}]
      
      function func(obj1, obj2){
        ...
      }
      
      func(...kwargs);
      
      **or more dynamically as:**
      
      const kwargs = [{"length": 1, "height": 2}, {"length":3, "height": 4}]
      
      function func(obj){
        for(const [key, value] of Object.entries(obj)){
          console.log(key, ": ", value)
       }
      
      func(kwargs);
      

      【讨论】:

      • 不可能在javascript中创建一个名为**kwargs的变量
      • 谢谢 Jake 会改正的
      猜你喜欢
      • 2017-05-17
      • 2020-09-16
      • 2017-01-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-24
      • 2013-07-04
      • 1970-01-01
      相关资源
      最近更新 更多