反思JavaScript:论for循环的死亡

我们一直在使用JavaScript的for循环。但现在,在最新的函数式编程技巧的支持下,过时的它应该退休了。幸运的是,你不必是一个函数式编程大师,也可以做出这个改变。更幸运的是,这就是你在眼前项目中可以立马做的事情!

我们一直在使用JavaScript的for循环。但现在,在最新的函数式编程技巧的支持下,过时的它应该退休了。

幸运的是,你不必是一个函数式编程大师,也可以做出这个改变。更幸运的是,这就是你在眼前项目中可以立马做的事情!

那到底JavaScript的for循环有什么问题?

for循环设计本身鼓励改变状态以及产生副作用,这两者都是导致错误和不可预知代码的隐患。

我们都知道全局状态是糟糕的,应该避免。可是,局部状态和全局状态一样糟糕,只是因为局部状态处于一个较小的尺度中,没有引起注意。因此,我们从来没有真正解决问题,而是尽量把问题最小化。

对于可变的状态,在一些未知的时间点,变量会因为某些未知的原因而改变。这时,你要花上数小时进行调试,寻找这个值改变的原因。光为这,我都不知道自己掉了多少把头发了。

下面,我想简单谈谈副作用。这个词听起来就烦人,副作用……妈蛋!难道你会希望自己的程序有什么副作用?当然不!

但什么是副作用?

当一个函数修改了其作用域以外的某些东西时,它就被视为有副作用。可以是改变一个变量的值、读取键盘输入、调用某个API、写入磁盘数据、打印日志,等等。

副作用很强大,但同时也被承担着重大的责任。

副作用应该尽可能被消除,或者封装在内部,或可控。有副作用的函数难以测试,也难以推断,所以要尽你所能甩掉它。幸好这里可以不用担心副作用。

好了,闲话少说,上代码。我们看一下这段或许你已经看过上千次典型的for循环:


  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.  
  9. // 典型的拙劣写法:for循环 
  10. for (var i = 0; i < cats.length; i++) { 
  11.   if (cats[i].months < 7) { 
  12.     kittens.push(cats[i].name) 
  13.   } 
  14.  
  15. console.log(kittens) 

我计划将这些代码一步一步重构,让你清楚地看到将这些代码转换成更漂亮的写法是多么容易。

第一个改变就是把if里的声明抽象为一个函数:


  1. const isKitten = cat => cat.months < 7 
  2.  
  3. var kittens = [] 
  4.  
  5. for (var i = 0; i < cats.length; i++) { 
  6.   if (isKitten(cats[i])) { 
  7.     kittens.push(cats[i].name) 
  8.   } 

通常,抽出if语句是个不错的做法。过滤的着眼点从“小于7个月”转变为“是一只小猫”非常非常重要。现在,当你再看这段代码,意图就变得清晰了。为什么要取得小于7个月的猫?一点都不明确。我们的意图是找到小猫,所以让代码表示出来!

另一个好处是iskitten现在可复用了,而且我们都明白:

让代码可复用应该始终是我们的目标之一。

下一个改变就是提取出从对象猫到猫名字的转换(或者映射)。这个变化对以后更有意义,现在只要相信我就好了:


  1. const isKitten = cat => cat.months < 7 
  2. const getName = cat => cat.name 
  3.  
  4. var kittens = [] 
  5.  
  6. for (var i = 0; i < cats.length; i++) { 
  7.   if (isKitten(cats[i])) { 
  8.     kittens.push(getName(cats[i])) 
  9.   } 

我本打算先介绍一下filter和map的,但转念一想,还是直接展示引入它们之后的代码多好理解,更能让你体会到代码可读性的巨大变化:


  1. const isKitten = cat => cat.months < 7 
  2. const getName = cat => cat.name 
  3.  
  4. const kittens = 
  5.   cats.filter(isKitten) 
  6.       .map(getName) 

还要注意,我们已经消除了 kittens.push(...)。不再有可变的状态,也不再有var!

使用const的代码有如魔鬼般性感(超过了var和let)。

这里说明下,我们自始至终都可以使用const,因为const并不会使对象本身不可变(这个咱们下次再说)。别急,这里只是在讲一个范例,所以先放我一马!

重构的最后一步就是把过滤和映射方法也提取到一个函数里(为了复用嘛,你懂的):

整合一起就是这样:


  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.  
  7. const cats = [ 
  8.   { name: 'Mojo',    months: 84 }, 
  9.   { name: 'Mao-Mao', months: 34 }, 
  10.   { name: 'Waffles', months: 4 }, 
  11.   { name: 'Pickles', months: 6 } 
  12.  
  13. const kittens = getKittenNames(cats) 
  14.  
  15. console.log(kittens) 

你会如何进一步分解这些函数?仔细想想“小于”或者name属性、map或filter,说不定能有额外的收获。你还可以研究下函数的复合,收益更大。

作者:camiler

来源:51CTO

时间: 2024-09-22 02:18:13

反思JavaScript:论for循环的死亡的相关文章

JavaScript的while循环的使用

  这篇文章主要介绍了详解JavaScript的while循环的使用,是JS入门学习中的基础知识,需要的朋友可以参考下 在写一个程序时,可能有一种情况,当你需要一遍又一遍的执行一些操作.在这样的情况下,则需要写循环语句,以减少代码的数量. JavaScript支持所有必要的循环,以帮助您在所有编程的步骤. while 循环 在JavaScript中最基本的循环是while循环,这将在本教程中学习讨论. 语法 ? 1 2 3 while (expression){ Statement(s) to

JavaScript中for循环的使用详解

  这篇文章主要介绍了JavaScript中for循环的使用详解,是JS入门学习中的基础知识,需要的朋友可以参考下 我们已经看到,while循环有不同变种.本章将介绍另一种流行的循环叫做for循环. for 循环 for循环是循环最紧凑的形式,并包含有以下三个重要部分组成: 循环初始化计数器的初始值.初始化语句执行循环开始之前. 测试语句,将测试如果给定的条件是真还是假.如果条件为真,那么将要执行的循环中给定的代码,否则循环会退出来. 循环语句,可以增加或减少计数器. 可以把所有的三个部分中的一

JavaScript数组和循环详解

          JavaScript数组和循环详解           这篇文章主要介绍了JavaScript数组和循环详解,本文讲解了循环遍历数组.按顺序存储和访问值.以相反的顺序存储和访问值.在数组中搜索等内容,需要的朋友可以参考下               数组是元素的一个有序组合.在JavaScript中,数组可以使用正式的对象表示法来创建,或者可以使用直接量表示法来初始化.   代码如下: var arrObject = new Array("val1", "

JavaScript在for循环中绑定事件解决事件参数不同的情况

响应一堆相似的事件,但是每个事件的参数都不同,在这种情况下就可以使用JavaScript 在for循环中绑定事件,下面有个不错的示例,大家可以参考下 有时候要对响应一堆相似的事件,但是每个事件的参数都不同,一开始还以为挺简单的,用个for循环不就得了,结果发现,额,都是使用了最后一个参数...  上网查资料!!!结果大神说用闭包解决  代码:  代码如下: for(var i=0;i<10;i++){  btns[i].onclick=(function(i){  return function

javascript实现图像循环明暗变化的方法

 这篇文章主要介绍了javascript实现图像循环明暗变化的方法,实例分析了javascript操作css样式的技巧,具有一定参考借鉴价值,需要的朋友可以参考下 本文实例讲述了javascript实现图像循环明暗变化的方法.分享给大家供大家参考.具体如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 <SCRIPT language=JavaScript> var d=0 function JM_fade(ob){ if (d==0) {ob.filters.alpha

javascript实现图片循环渐显播放的方法_javascript技巧

本文实例讲述了javascript实现图片循环渐显播放的方法.分享给大家供大家参考.具体实现方法如下: 复制代码 代码如下: <html> <title>图片的循环渐显播放效果代码</title> <head> <!--1.将下面的代码插入到HEML的<head></head>之间: --> <script language=javaScript> <!--// sandra0 = new Image()

javascript的for循环变量的初始化问题

问题描述 javascript的for循环变量的初始化问题 为什么声明的变量位置不一样得出的结果也不一样?在for循环外面和在for里面声明变量i 和j并初始化赋值0,结果不一样. <html> <head> <meta charset="utf-8"/> <title></title> <style type="text/css"> *{ padding:0; margin:0; font-s

javascript实现图像循环明暗变化的方法_javascript技巧

本文实例讲述了javascript实现图像循环明暗变化的方法.分享给大家供大家参考.具体如下: <SCRIPT language=JavaScript> var d=0 function JM_fade(ob){ if (d==0) {ob.filters.alpha.opacity+=1} else {ob.filters.alpha.opacity-=1} if (ob.filters.alpha.opacity==100){d=1;} else if (ob.filters.alpha.

java、python、JavaScript以及jquery循环语句的区别_java

一.概述        python中循环语句有两种,while,for: JavaScript中循环语句有四种,while,do/while,for,for/in jQuery循环语句each 二.java 循环语句          a.while                 while 的语法为: while(条件语句){ 代码块 }           或者: while (条件语句) 代码; while的含义非常简单,只要条件语句为真,就一直执行后面的代码,为假就停止不做了.例如: