通过函数调用迭代

Seb*_*ian 1 javascript c++ functional-programming d3.js

经过多年在C++中编写循环这种繁琐的方式

for(int i=0; i<N; ++i) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

使用迭代器变得相当不错

for(it i=v.begin(); i<v.end(); ++i) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

并最终转移到范围迭代器

for(auto i:v) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

在JavaScript中,也for可以使用几乎相同的样式(减去类型声明和前/后增量运算符)到上面的第一个样式.

在所有这些中,for仍然存在.该D3.js 库演示的替代品.可以通过写入迭代数组

d3.select("body")
  .selectAll("p")
  .data([4, 8, 15, 16, 23, 42])
  .enter().append("p")
  .text(function(d) { return "I’m number " + d + "!"; });
Run Code Online (Sandbox Code Playgroud)

这里enter变异为for循环.该文档 很好地解释了连接的客户端视图.我缺少的是将函数调用转换为迭代的(函数式编程?)风格的独立示例.

毫无疑问,这不是D3.js独有的.这就是我遇到成语的地方.

您能否建议几行独立的JavaScript代码来演示函数调用的迭代?

Igo*_*nko 5

我想到至少有几个内置函数.

地图()

这一点非常明显.

[1, 2, 3]
  .map(someNumber => someNumber * someNumber)
  .map((powered, index) => index + "::" + powered);

  // --> [ "1::1", "2::4", "3::9" ]
Run Code Online (Sandbox Code Playgroud)

链好,对吧?获取一些输入并产生由通过应用元素方式计算的元素组成的结果.

建议:尽可能使用纯函数(对于相同的输入产生相同的结果,如果可能,不要改变原始集合,也不产生任何副作用).

的forEach()

此函数也遍历数组的所有元素,并应用函数,而不返回任何内容.因此,它只能结束一系列调用,但不能用于进一步链接.

[1, 2, 3, 4]
  .forEach(number => console.info(number));
Run Code Online (Sandbox Code Playgroud)

建议: forEach()当我们想要编写一些代码时会很有用,这些代码会导致迭代集合中每个条目产生副作用.

过滤()

过滤函数使用谓词来从谷壳中筛选出小麦.谓词定义了您想要在下一个"阶段"处理的项目的标准.

[null, undefined, 0, 1, 2, 3, NaN, "", "You get the idea"]
  .filter(Boolean)
  .map(filteredElement => filteredElement + "!")

  // --> [ "1!", "2!", "3!", "You get the idea!" ]
Run Code Online (Sandbox Code Playgroud)

建议:尽可能使用纯函数.即filter除了与过滤逻辑本身直接相关的事物之外,其他任何事情都不做.

Object.keys()和Object.entries()

当我们需要迭代对象的键或键值对而不是数组的元素时,这两个函数很有用.

const targetObject = { a: 1, b: 2, c: 3 };
Object
  .keys(targetObject)
  .map(key => key + "=" + targetObject[key])

  // --> [ "a=1", "b=2", "c=3" ]
Run Code Online (Sandbox Code Playgroud)

可以像这样实现相同的结果

Object
  .entries({ a: 1, b: 2, c: 3 })
  .map((key, value) => key + "=" + value)

  // --> [ "a=1", "b=2", "c=3" ]
Run Code Online (Sandbox Code Playgroud)

建议:您可能希望在使用Object.hasOwnProperty(...)时使用Object.keys(...).有关详细信息,请参阅文档

找()

这个几乎是微不足道的.让我们搜索与谓词匹配的项目.搜索是"从左到右",只要找到第一个"匹配",它就会停止.

[1, 5, 10, 15]
  .find(number >= 7)

  // --> 10
Run Code Online (Sandbox Code Playgroud)

当我们查找与谓词匹配的元素的位置时,可以使用findIndex()函数.

some()和every()

这些功能检查是否

a)至少有一个元素与谓词匹配; 或b)每个元素都与谓词匹配.

const arrayOfNumbers = [2, 4, 6, 8, 10];

arrayOfNumbers.every(number => number % 2 === 0); // --> true
arrayOfNumbers.every(number => number % 2 === 1); // --> false

arrayOfNumbers.some(number => number > 1);        // --> true
arrayOfNumbers.some(number => number <= 1);       // --> false
Run Code Online (Sandbox Code Playgroud)

reduce()和`reduceRight()`

本快速回顾中提到的最后一个是获取事物列表并将其聚合到单个结果中的函数.

[-1, 0, 1, 2, 3]
  .filter(value => value >= 0) // [0, 1, 2, 3]
  .map(value => value + 1)     // [1, 2, 3, 4]
  .reduce((subTotal, currentValue) => subTotal + currentValue, 5);

  // --> 15
Run Code Online (Sandbox Code Playgroud)

建议:尽可能使用纯函数.


普遍适用的绩效说明.在我的基准测试(没有他们的手),手写for循环总是要快forEach,map和其他迭代功能.除非性能受到严重影响,否则我仍然更喜欢这些功能.有两个主要原因:1)更容易避免一个错误; 2)代码更具可读性,因为每个单个函数在数据处理流程中定义了一个独立的步骤,从而使代码更简单,更易于维护.


我希望,这是对一些内置的可链式JavaScript函数的概述.这里描述了更多.看看concat(),sort(),fill(),join(),slice(),reverse()-我经常使用他们.

如果你需要这样的东西first()或者last(),你会不会在本机的功能找到它们.编写自己的库,或使用第三方库(例如lodash,rambda.js).