UDN-企业互联网技术人气社区

板块导航

浏览  : 1085
回复  : 11

[原生js] JavaScript For 循环的函数式改造

[复制链接]
genie1003的头像 楼主
发表于 2017-2-9 10:49:51 | 显示全部楼层 |阅读模式
  For 循环的设计思想深受可变状态与副作用的影响,不过函数式编程中认为可变状态与副作用是导致潜在错误与不可预测性的罪魁祸首,是应该尽力避免的模式。众所周知,使用全局状态会污染局部代码,而同样的局部状态同样会导致与全局状态一样的问题,只不过因为局部状态的影响被限制在较小的影响范围内,因此不像全局状态那样的突兀。允许可变的状态也就意味着变量可能因为未知的原因被改变,开发者可能要花费数小时的时间去定位到底是哪一段代码修改了这个变量值。在过去的开发岁月里,我就是因为这样变秃了,却似乎没有变强。

  另一方面,任何修改除了作用域内变量值的函数都被称为有副作用的函数。典型的譬如修改全局变量、读入键盘输入、调用远程 API 、写入磁盘等等。副作用的功效强大,我们应该尽可能地将其封装与控制在一定范围内。大道理就回顾到这里,下面我们直接看下代码:
  1. const cats = [
  2.   { name: 'Mojo',    months: 84 },
  3.   { name: 'Mao-Mao', months: 34 },
  4.   { name: 'Waffles', months: 4 },
  5.   { name: 'Pickles', months: 6 }
  6. ]
  7. var kittens = []
  8. //典型的 for 循环用法
  9. for (var i = 0; i < cats.length; i++) {
  10.   if (cats[i].months < 7) {
  11.     kittens.push(cats[i].name)
  12.   }
  13. }
  14. console.log(kittens)
复制代码

  我们改造的第一步是将 if 语句中的逻辑判断提取出来,老实说提取之后笔者觉得正好符合 Clean JavaScript:写出整洁的JavaScript代码 里面提及的让变量名而不是注释表述其含义的效果:
  1. const isKitten = cat => cat.months < 7
  2. var kittens = []
  3. for (var i = 0; i < cats.length; i++) {
  4.   if (isKitten(cats[i])) {
  5.     kittens.push(cats[i].name)
  6.   }
  7. }
复制代码

  这种方式一方面增加了代码的可用性,另一方面也保证了我们测试条件的可测试性,特别是当我们的逻辑判断很复杂的时候。下面我们是将属性提取也抽象出来:
  1. const isKitten = cat => cat.months < 7
  2. const getName = cat => cat.name
  3. var kittens = []
  4. for (var i = 0; i < cats.length; i++) {
  5.   if (isKitten(cats[i])) {
  6.     kittens.push(getName(cats[i]))
  7.   }
  8. }
复制代码

  下面我们可以用函数式中的过滤与转换函数来描述这个过程:
  1. const isKitten = cat => cat.months < 7
  2. const getName = cat => cat.name
  3. const kittens =
  4.   cats.filter(isKitten)
  5.       .map(getName)
复制代码

  到这里我们摒弃了 push 函数,即移除了可变状态的介入。最后的重构即是将我们的过滤与转换过程再进行一层封装,使其成为可复用的过程:
  1. const isKitten = cat => cat.months < 7
  2. const getName = cat => cat.name
  3. const getKittenNames = cats =>
  4.   cats.filter(isKitten)
  5.       .map(getName)
  6. const cats = [
  7.   { name: 'Mojo',    months: 84 },
  8.   { name: 'Mao-Mao', months: 34 },
  9.   { name: 'Waffles', months: 4 },
  10.   { name: 'Pickles', months: 6 }
  11. ]
  12. const kittens = getKittenNames(cats)
  13. console.log(kittens)
复制代码

相关帖子

发表于 2017-2-9 10:50:30 | 显示全部楼层
js是要逆天的节奏js虽然不错,但是天生也是有缺陷,局限性。。。
使用道具 举报

回复

发表于 2017-2-10 17:39:00 来自手机 | 显示全部楼层
鄙视楼下的顶帖没我快,哈哈
使用道具 举报

回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关于我们
联系我们
  • 电话:010-86393388
  • 邮件:udn@yonyou.com
  • 地址:北京市海淀区北清路68号
移动客户端下载
关注我们
  • 微信公众号:yonyouudn
  • 扫描右侧二维码关注我们
  • 专注企业互联网的技术社区
版权所有:用友网络科技股份有限公司82041 京ICP备05007539号-11 京公网网备安1101080209224 Powered by Discuz!
快速回复 返回列表 返回顶部