【问题标题】:recursively concatenating a javascript functions arguments递归连接一个javascript函数参数
【发布时间】:2010-10-04 17:30:59
【问题描述】:

我遇到了一个 javascript 难题,询问: 编写一段 JavaScript 代码,将传递给函数的所有字符串连接起来:

function concatenate(/*any number of strings*/) { var string = /*your one line here*/ return string; }

@meebo

看到函数参数被表示为一个索引对象可能是一个数组,我认为可以以递归方式完成。但是我的递归实现抛出了一个错误。 --"conc.arguments.shift 不是函数"--

function conc(){ if (conc.arguments.length === 0) return ""; else return conc.arguments.shift() + conc(conc.arguments); }

好像 conc.arguments 不是一个数组,而是可以通过数字索引访问并具有长度属性???令人困惑 - 请分享意见和其他递归实现。

谢谢

【问题讨论】:

    标签: javascript recursion variadic-functions


    【解决方案1】:

    参数列表不是真正的数组。我认为您可以借用数组方法并将它们用于带有“调用”或“应用”的参数。

    【讨论】:

      【解决方案2】:

      Mozilla on the subject:

      参数对象不是数组。它 类似于数组,但没有任何数组 除长度外的属性。例如, 它没有 pop 方法。 但是它可以转换为真实的 数组:

      var args = Array.prototype.slice.call(arguments);
      

      因此,您的问题的解决方案相当简单:

      var string = Array.prototype.slice.call(arguments).join("");
      

      顺便说一句:它进一步指出:

      arguments 对象是本地的 变量在所有可用 职能;论据作为属性 函数不能再使用了。

      您应该只使用arguments 而不是func.arguments

      【讨论】:

      • 或者,Array.prototype.join.call(arguments, '')
      【解决方案3】:

      arguments is said to be 一个类似数组的对象。正如您已经看到的,您可以通过索引访问它的元素,但您没有所有的 Array 方法可供您使用。类似数组的对象的其他示例是由 getElementsByTagName() 或 getElementsByClassName() 返回的 HTML 集合。 jQuery,如果你曾经使用过它,它也是一个类似数组的对象。在查询了一些 DOM 对象后,在 DOM 选项卡中使用 Firebug 检查生成的 jQuery 对象,你就会明白我的意思了。

      这是我对 Meebo 问题的解决方案:

      function conc(){
          if (arguments.length === 0)
              return "";
          else
              return Array.prototype.slice.call(arguments).join(" ");
      }
      
      alert(conc("a", "b", "c"));
      

      Array.prototype.slice.call(arguments) 是将我们的arguments 转换为名副其实的 Array 对象的好技巧。在 Firefox 中 Array.slice.call(arguments) 就足够了,但它在 IE6 中不起作用(至少),所以通常使用的是以前的版本。此外,此技巧不适用于 IE6 中的 DOM API 方法返回的集合(至少);它会抛出一个错误。顺便说一句,可以使用apply 代替call

      关于类数组对象的一点解释。在 JavaScript 中,您几乎可以使用任何东西来命名对象的成员,数字也不例外。所以你可以构造一个看起来像这样的对象,它是完全有效的 JavaScript:

      var Foo = {
          bar : function() {
              alert('I am bar');
          },
      
          0 : function() {
              alert('I am 1');
          },
      
          length : 1
      }
      

      上述对象是一个类数组对象,原因有二:

      1. 它的成员名称是数字,所以它们就像数组索引
      2. 它有一个length 属性,如果没有它,您将无法使用以下构造将对象转换为真正的数组:Array.prototype.slice.call(Foo);

      Function 对象的 arguments 对象与 Foo 对象非常相似,只是它有其特殊用途。

      【讨论】:

        【解决方案4】:

        你可以这样做:

        function concatenate() {
            if (arguments.length > 1) {
                return arguments[0] + concatenate.apply(this, Array.prototype.splice.call(arguments, 1));
            }
            return arguments[0];
        }
        

        【讨论】:

          【解决方案5】:

          这行得通:

          function concatenate(){
              return [].join.call(arguments, "");
          }
          alert(concatenate("one", "two", "three"));
          

          【讨论】:

          • 你为什么不用 3 个字符串参数而不是 1 个数组参数和 3 个字符串调用函数?那将摆脱逗号:) 我真的很喜欢这个解决方案。 +1
          • 因为我又累又病!感谢您指出我的愚蠢,现在它起作用了。
          【解决方案6】:

          它至少可以与Array.prototype 的 6 种不同方法一起使用(我怀疑还有更多),即joinslicespliceconcatreduceflat。可能最短的方法是使用join,也就是上面@svinto 的解决方案。 g 与 @GeorgSchölly 的答案相同。

          瞧,六种解决方案:

          function f(){
            return [].join.call(arguments,'');
          }
          function g(){
            return [].slice.call(arguments).join('');
          }
          function h(){
            return [].splice.call(arguments,0).join('');
          }
          function i(){
            return [].concat.apply([], arguments).join('');
          }
          function j(){
            return [].reduce.call(arguments,function(buff,x){return buff+x},'');
          }
          function k(){
            return [].flat.call(arguments).join('');
          }
          document.getElementById('F').textContent = f('a','b','c');
          document.getElementById('G').textContent = g('a','b','c');
          document.getElementById('H').textContent = h('a','b','c');
          document.getElementById('I').textContent = i('a','b','c');
          document.getElementById('J').textContent = j('a','b','c');
          document.getElementById('K').textContent = k('a','b','c');
          <pre id='F'></pre>
          <pre id='G'></pre>
          <pre id='H'></pre>
          <pre id='I'></pre>
          <pre id='J'></pre>
          <pre id='K'></pre>

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2022-01-02
            • 1970-01-01
            • 1970-01-01
            • 2014-12-20
            • 1970-01-01
            • 2019-05-08
            • 2016-07-22
            • 2011-06-06
            相关资源
            最近更新 更多