Fab*_*oli 5 javascript arrays functional-programming
迭代在 javascript 中迭代期间增长的数组的最聪明方法是什么?我想遍历所有添加的元素,甚至是在迭代过程中添加的元素。我想用函数式编程风格来做。
例如看这个代码
let a = [
'x',
'y'
]
let limit = 4 // limit the test
for (let i=0; i<a.length; i++) {
console.log(a[i])
limit--
if(limit>0){
a.push(a[i]+'-')
}
}
console.log(a)Run Code Online (Sandbox Code Playgroud)
执行后得到
[
"x",
"y",
"x-",
"y-",
"x--"
]
Run Code Online (Sandbox Code Playgroud)
但是,如果我尝试使用替代的“功能”模式,例如 forEach,则不会打印新添加的元素
[
"x",
"y",
"x-",
"y-",
"x--"
]
Run Code Online (Sandbox Code Playgroud)
正如鲁本斯正确地注意到的那样,函数式方法假定您的函数不会改变源数据,而是对其进行转换并返回新值。
在以下示例中,源数组保持不变,并transform通过递归调用自身并传递更新的参数来遍历它:
function transform(array, limit, acc = []) {
if (limit === 0 || array.length === 0) {
return acc;
}
const head = array[0];
const tail = array.slice(1);
return transform(tail.concat(head + "-"), limit - 1, acc.concat(head));
}
transform(["x", "y"], 5).forEach(x => console.log(x))Run Code Online (Sandbox Code Playgroud)
结果数组受limit参数限制,这limit = 5意味着结果中只有 5 个元素。
如果我们查看在transform每次迭代时传递给函数的参数,我们会看到limit当acc( 的缩写accumulator)接收新元素时,它会变小:
transform(["x", "y"], 5, [])
transform(["y", "x-"], 4, ["x"])
transform(["x-", "y-"], 3, ["x", "y"])
transform(["y-", "x--"], 2, ["x", "y", "x-"])
transform(["x--", "y--"], 1, ["x", "y", "x-", "y-"])
transform(["y--", "x---"], 0, ["x", "y", "x-", "y-", "x--"])
Run Code Online (Sandbox Code Playgroud)
当limit达到零时,acc作为结果返回值。请注意,没有数据发生变异。
值得一提的是transformcall 处于尾部位置,并且由于 ES6优化了尾部调用(在严格模式下),我们不必担心调用堆栈的增长。
另请注意,上面的代码仅说明了这个想法。应该小心使用它,因为它在大量数据上可能会非常慢,因为每次迭代都会有sliceing 和concating 数组。
尾调用优化更新:尽管尾调用优化是 ES6 规范的一部分,但浏览器并不广泛支持它,因此在使用递归时需要谨慎。请参阅兼容性表。
| 归档时间: |
|
| 查看次数: |
1426 次 |
| 最近记录: |