与循环相比,使用函数有什么优点?

2023-12-03

函数式迭代器似乎正在取代 JS 中 for 循环的使用。

传递诸如此类的函数有什么好处map or reduce与 for/while 循环相比?

var numbers = [1, 4, 9];
var doubles = numbers.map(function(num) {
  return num * 2;
});

var doubles = [];
for (i = 0; i < numbers.length; i++) { 
    doubles[i] = numbers[i] * 2;
}

我不知道你为什么会调用map一个“关闭”。闭包完全是另一回事。map是一个高阶函数——定义为对函数进行操作(获取或返回)的函数。这种编程风格可以粗略地称为“函数式”。

使用类似的函数有优点和缺点map。正如一位评论者指出的那样,它更加紧凑:

function sum(array) {
  var sum = 0;
  for (var i = 0; i < array.length; i++) sum += array[i];
  return sum;
}

vs.

function sum(array) {
  return array.reduce(add);
}

Where add is function add(a, b) { return a + b; }.

更紧凑意味着更具可读性并且更小的 bug 表面积。使用名为add还增强了可读性;我们很容易直觉到该操作就是将数组的元素相加。

基本上,所有数组函数都有 for 循环等效项,这需要设置更多变量并编写更多逻辑。例如,map is

function map(array, fn) {
  var result = [];
  for (var i = 0; i < array.length; i++) result.push(fn(array[i]));
  return result;
}

这可以更紧凑地写为array.map(fn).

在许多情况下,我们可能已经定义了执行元素映射或我们想要执行的元素过滤的函数。在这种情况下,我们可以简单地使用这些函数map, reduce etc.

map它的朋友们还有一个优点,那就是对稀疏数组很友好。例如:

var a = [];
a[1000000] = 1;

现在我们将每个元素加倍:

function double(array) {
  var result = [];
  for (var i = 0; i < array.length; i++) result.push(array[i] * 2); 
  return result;
}

这会循环一百万次并返回一个充满 NaN 的数组。相比之下

array.map(elt => elt*2)

仅对位置 1000000 处存在的单个元素进行操作,并根据需要返回一个稀疏数组。

功能性风格还为灵活性提供了额外的可能性。假设我们想要概括乘法的想法。我可以编写一个高阶函数来创建一个将某个值乘以特定因子的函数:

function multiply(n) {
  return function(x) {
    return n * x;
  };
}

现在我可以写了

array.map(multiply(2))

在 for 循环解决方案中很难实现这种程度的简洁性和表现力。

forEach and map等可能比 for 循环慢。如果您的代码在紧密循环中运行一百万次,这可能会成为一个问题。在现实世界中,这很少是一个问题。最好优先考虑代码的可读性和紧凑性。

然而,没有人强迫你使用map or filter。在 ES7 或其他任何名称中,您将能够使用数组推导式以更易读的方式完成相同的事情:

[ for (i of array) if (i % 2) i + 1 ]

它结合了过滤器和地图。

更远一点,如果您计划编写一个迭代数组的生成器,并从每个元素生成一些计算,您将需要使用 for 循环,因为无法从forEach打回来:

function *double(array) {
  for (var i = 0; i < array.length; i++) yield array[i]*2;
}

function *double(array) {
  array.forEach(elt => yield elt*2); // DOESN'T WORK!!
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

与循环相比,使用函数有什么优点? 的相关文章

随机推荐

  • 如何在VSCode中添加自定义代码片段?

    是否可以在 Visual Studio Code 中添加自定义代码片段 如果是这样 怎么办 VSCode是基于Atom的 所以应该是可以的 Hit gt shift command p and type snippets Select 首选
  • 如何在 Unity 中全局创建类的别名?

    现在 我正在使用 字符串 来枚举角色上的设备槽列表 我还使用 string 来枚举该项目可以装备的类类型 这使得我获取 删除 生成等项目的所有方法都涉及两个字符串参数 即设备槽和类类型 我真正想要的是使用 2 个类 这样我就有了 slot
  • 单击通知时获取 PendingIntent 事件

    我试图在单击通知时单击事件 我拥有的 NotificationManager notificationManager NotificationManager getSystemService Context NOTIFICATION SER
  • 在 PySpark Builder 中设置 PySpark 序列化器

    我正在使用 PySpark 2 1 1 并尝试在使用 Spark Submit 时设置序列化器 在我的应用程序中 我按如下方式初始化 SparkSession builder print creating spark session spa
  • 如何在R中直接绘制h2o模型对象的ROC

    如果我遗漏了一些明显的东西 我很抱歉 在过去的几天里 我非常喜欢使用 R 界面与 h2o 一起工作 我想通过绘制 ROC 来评估我的模型 例如随机森林 该文档似乎表明有一种简单的方法可以做到这一点 解释 DRF 模型 默认情况下 显示以下输
  • 写入会话数据失败

    在长时间使用同一应用程序而没有更改编程后 我收到了此消息 Warning Unknown write failed No space left on device 28 in Unknown on line 0 Warning Unknow
  • 在 JavaScript 中获取两个日期的秒数差异

    我使用 Date 将日期存储在 MongoDB 中 MongoDB 使用 UTC 它的日期类型 字符串看起来像Mon 02 Apr 2012 20 16 31 GMT 我想获得当前时间与当前时间 UTC 时间 之间的时间差 以总秒数为单位
  • 在某些观察结果之前选择组,通过将 R 中的 var 分组与 NA 控制分开

    我的样品 data structure list add structure c 1L 1L 1L 1L 1L 1L 1L 1L 1L 1L 1L 1L 1L 1L 1L 1L 1L 1L 1L 1L 1L 1L 1L 1L 1L 1L 2
  • Android:后退按钮中的 onSaveInstanceState

    我正在开发一个应用程序 其中我将覆盖后退按钮 我创建了一个复选框 单击后我调用意图 startActivityforResult 并且还保持活动状态为 Override public void onSaveInstanceState Bun
  • SQL Server 日期时间 LIKE 选择?

    在MySQL中 select from record where register date like 2009 10 10 SQL Server 中的语法是什么 您可以使用 DATEPART 函数 SELECT FROM record W
  • PHP 中的工厂设计模式是什么?

    这让我很困惑 用最简单的术语来说 它有什么作用 假装你正在向你的母亲或其他人解释 工厂创建一个对象 所以 如果你想构建 class A public classb public classc public function construc
  • 对象数组的 Var-arg 与对象数组——尝试理解 SCJP 自测问题

    我无法理解这个问题以及 SCJP 1 6 自测问题答案的解释 问题是这样的 class A class B extends A public class ComingThru static String s public static vo
  • C++ 返回并插入二维数组对象

    我试图从一个较小的 2D 数组对象返回一个数组数据成员 并尝试将该数组插入到一个更大的 2D 数组对象中 但当我尝试这样做时 我遇到了两个问题 第一个问题是我想返回 2D 数组的名称 但我不知道如何正确的语法来返回 2D 数组名称 这就是我
  • 获取值和位置来标记 ggplot 直方图

    下面的代码运行良好 并且它正确地标记了条形图 但是 如果我尝试geom text对于直方图我失败了geom text需要一个y 分量和直方图y组件不是原始数据的一部分 标记 普通 条形图 geom bar stat identity 效果很
  • 使用C#获取插入行的id

    我有一个查询要在表中插入一行 该表有一个名为 ID 的字段 该字段是使用列上的 AUTO INCRMENT 填充的 我需要为下一个功能获取这个值 但是当我运行以下命令时 它总是返回 0 即使实际值不为 0 MySqlCommand comm
  • iOS 上的自定义键盘:如何访问 UITextField?

    我有一个UIView我分配给文本字段的子类如下 self textField inputView HexKeyboard alloc initWithFrame CGRectMake 0 0 100 100 这有效 即键盘出现 然而 应该如
  • 提取以特定字符开头的几个单词EXCEL

    我有这个公式来提取以给定字符 开头的特定单词 它工作正常 但是 有更多以相同开头的单词 它只会提取第一个单词 如何让它全部提取出来 TRIM LEFT SUBSTITUTE MID B2 FIND B2 LEN B2 REPT 100 10
  • 为 n 维系统实现模块化 Runge-kutta 四阶方法

    我正在尝试使我的 runge kutta 四阶代码模块化 我不想每次使用它时都必须编写和声明代码 但是在 hpp和 cpp文件中声明它以分别使用它 但我遇到了一些问题 一般来说 我想求解 n 维方程组 为此 我使用两个函数 一个用于方程组
  • 如何在谷歌浏览器中创建侧边栏(右侧)?

    似乎这是不可能的 但如果有人提示如何在 google chrome 中创建右侧边栏 如 iframe 任何提示都会有所帮助 谢谢 截至目前 实验性侧边栏 API 已从 Chrome 文档中消失 因为不再有开发人员在处理它 对于现在可以实现的
  • 与循环相比,使用函数有什么优点?

    函数式迭代器似乎正在取代 JS 中 for 循环的使用 传递诸如此类的函数有什么好处map or reduce与 for while 循环相比 var numbers 1 4 9 var doubles numbers map functi