我遇到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]));
的执行方式吗?
答案 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
flatten
(this
指向全球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 + ''
});
}
);
没有用处代码示例中的对象。)