递归Function.prototype.apply概念性理解

时间:2016-03-29 19:10:28

标签: javascript arrays recursion

我遇到this stackoverflow question关于递归展平JS数组的问题。这是接受的答案:

function flatten() {
    var flat = [];
    for (var i = 0; i < arguments.length; i++) {
        if (arguments[i] instanceof Array) {
            flat.push.apply(flat, flatten.apply(this, arguments[i]));
        } else {
            flat.push(arguments[i]);
        }
    }
    return flat;
}

flatten([[1], 2, [3, 4]]); // returns [1, 2, 3, 4]

我无法理解flat.push.apply(...)flatten.apply(...)的工作原理。

据我所知,只有当数组中的项的 none 是数组本身时,该函数才会退出。我也明白Function.prototype.apply()允许你使用一组参数调用一个函数。

我不理解的是,如果flat.push...在每次函数迭代时都设置为flat,则使用[]的原因。另外,将flat设置为this上下文有什么意义?

有人可以帮助解释flat.push.apply(flat, flatten.apply(this, arguments[i]));的执行方式吗?

1 个答案:

答案 0 :(得分:2)

他安全地使用flat.push,因为每次都会在不同的数组上调用push。每次flatten执行时,它都会创建一个新数组,其中包含存储在flat变量中的不同引用,因此每个递归都与不同的flat数组相关联。

flat设置为this上下文可以将数组称为push。尝试将其设置为null,由于非法操作,您可能会获得TypeError - 尝试拨打push上的null

现在是更复杂的部分。 push接受要添加到数组的参数列表,对吗?但有时一个接一个地提供这些参数并不方便,特别是,如果你不知道,有多少push应该接收,就像在你的情况下,要变平的数组的大小不同。

这就是为什么该代码的作者通过push通过数组引用作为第二个参数调用apply - 这是flatten.apply(this, arguments[i])的返回值 - 对当时只包含数字的数组的引用。该数组的每个数字都被推送到flat,因为apply调用了push并通过push的参数传递了该数组的整个数字列表。

由于类似的原因,flatten.apply(this, arguments[i])部分通过apply调用 - 它利用arguments(每个函数具有类似数组的对象)来轻松处理函数args。在this的第一个arg中移交apply并不重要,因为this flattenthis指向全球bigquery.defineFunction( 'newdate', // Name of the function exported to SQL [], // Names of input columns [ {name: 'date', type: 'timestamp'} , {name: 'datestr', type: 'string'} ], function newDate(row, emit) { var date = new Date(); // current date and time emit({ date: date , datestr: date + '' }); } ); 没有用处代码示例中的对象。)