6

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


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

@米波

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


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

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

谢谢

4

6 回答 6

13

arguments 据说是一个类似数组的对象。正如您已经看到的,您可以通过索引访问它的元素,但是您没有所有的 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 对象是一个不错的技巧。在 FirefoxArray.slice.call(arguments)中就足够了,但它不会在 IE6 中工作(至少),所以以前的版本是通常使用的。此外,这个技巧不适用于 IE6 中的 DOM API 方法返回的集合(至少);它会抛出一个错误。顺便说一句,call可以使用apply.

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

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

    0 : function() {
        alert('I am 1');
    },

    length : 1
}

上面的对象是一个类似数组的对象,原因有两个:

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

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

于 2009-02-01T00:18:10.357 回答
7

Mozilla 关于这个主题

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

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

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

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

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

arguments 对象是所有函数中可用的局部变量;不能再使用作为 Function 属性的参数。

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

于 2009-02-01T00:07:14.030 回答
6

这有效:

function concatenate(){
    return [].join.call(arguments, "");
}
alert(concatenate("one", "two", "three"));
于 2009-02-01T00:20:17.920 回答
1

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

于 2009-01-31T23:56:05.190 回答
1

你可以这样做:

function concatenate() {
    if (arguments.length > 1) {
        return arguments[0] + concatenate.apply(this, Array.prototype.splice.call(arguments, 1));
    }
    return arguments[0];
}
于 2009-02-01T00:18:32.773 回答
0

它至少可以使用 6 种不同的方法Array.prototype(我怀疑还有更多),即join, slice, splice, concat, reduce, flat。可能最短的方法是 using 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>

于 2019-12-28T02:30:43.870 回答