重写展平函数
Rewriting the flatten function
我写了下划线 _.flatten 函数的一个版本,它可以工作,但我不明白为什么第一个版本有效而第二个版本不行。
var flatten = function (array, result) {
var result = [];
for (var i = 0; i < array.length; i++) {
var current = array[i];
if (Array.isArray(current)) {
result.push.apply(array, flatten(current));
}
else {
result.push(current);
}
}
return result;
};
var nested = [1, [2], [3, [[[4]]]]];
console.log(flatten(nested));
// [1,2,3,4]
对比:
var flatten = function (array, result) {
var result = [];
array.forEach(function (current) {
if (Array.isArray(current)) {
result.push.apply(array, flatten(current));
}
else {
result.push(current);
}
});
return result;
};
var nested = [1, [2], [3, [[[4]]]]];
console.log(flatten(nested));
// [1]
您将错误的第一个参数传递给 result.push.apply
:
result.push.apply(array, flatten(current));
// ---------------^^^^^
您想在 result
上呼叫 push
,但您实际上是在呼叫 array.push
。你想说:
result.push.apply(result, flatten(current));
以便 push
在被调用时得到 result
作为它的 this
。
一个更有趣的问题是,为什么您基于 for
的实现 "works" 尽管其实现很混乱。如果你抛出一个
console.log(nested);
在第一个的底部,您会看到基于 for
的实现弄乱了它的论点;因此 "works".
上的惊吓引用
如果您在心理上逐步完成 if
:
if (Array.isArray(current)) {
result.push.apply(array, flatten(current));
}
else {
result.push(current);
}
您会看到它在迭代时正在修改 array
。但是它添加到 array
的所有内容都是另一个数组,而非数组最终会出现在 result
您想要的位置。
如果您开始于:
var nested = [1, [2], [3, [[[4]]]], 5]
你会发现它不能以另一种方式工作,因为你最终会得到:
[1, 5, 2, 3, 4]
作为你的最终结果(以及 nested
中的一些其他混乱)。您的基于 for
的实现之所以有效,是因为您碰巧给了它一个特殊结构的输入。
我写了下划线 _.flatten 函数的一个版本,它可以工作,但我不明白为什么第一个版本有效而第二个版本不行。
var flatten = function (array, result) {
var result = [];
for (var i = 0; i < array.length; i++) {
var current = array[i];
if (Array.isArray(current)) {
result.push.apply(array, flatten(current));
}
else {
result.push(current);
}
}
return result;
};
var nested = [1, [2], [3, [[[4]]]]];
console.log(flatten(nested));
// [1,2,3,4]
对比:
var flatten = function (array, result) {
var result = [];
array.forEach(function (current) {
if (Array.isArray(current)) {
result.push.apply(array, flatten(current));
}
else {
result.push(current);
}
});
return result;
};
var nested = [1, [2], [3, [[[4]]]]];
console.log(flatten(nested));
// [1]
您将错误的第一个参数传递给 result.push.apply
:
result.push.apply(array, flatten(current));
// ---------------^^^^^
您想在 result
上呼叫 push
,但您实际上是在呼叫 array.push
。你想说:
result.push.apply(result, flatten(current));
以便 push
在被调用时得到 result
作为它的 this
。
一个更有趣的问题是,为什么您基于 for
的实现 "works" 尽管其实现很混乱。如果你抛出一个
console.log(nested);
在第一个的底部,您会看到基于 for
的实现弄乱了它的论点;因此 "works".
如果您在心理上逐步完成 if
:
if (Array.isArray(current)) {
result.push.apply(array, flatten(current));
}
else {
result.push(current);
}
您会看到它在迭代时正在修改 array
。但是它添加到 array
的所有内容都是另一个数组,而非数组最终会出现在 result
您想要的位置。
如果您开始于:
var nested = [1, [2], [3, [[[4]]]], 5]
你会发现它不能以另一种方式工作,因为你最终会得到:
[1, 5, 2, 3, 4]
作为你的最终结果(以及 nested
中的一些其他混乱)。您的基于 for
的实现之所以有效,是因为您碰巧给了它一个特殊结构的输入。