本文章记录本人在深刻学习js
循环中看书理解到的一些东西,加深记忆和而且整理记录下来,方便以后的复习。html
在大部分编程语言中,代码执行的时间多数消耗在循环的执行上。算法
js
定义了4种类型的循环:for, while, do while, for in
。编程
for
循环是最经常使用的循环结构,它由四个部分组成:segmentfault
当遇到一个for
循环的时候,初始化体首先执行,而后进入前测条件。若是前测条件的计算为true
,就会执行循环体,而后运行后执行条件。数组
Javascriptfor (var i = 0; i < 10; i++) { // 循环体 };
while
循环是一个简单的前测循环,由一个前测条件和一个循环体构成。在执行循环体以前,先对前测条件进行计算。若是为true
就执行循环体。不然就会跳过循环体。浏览器
Javascriptvar i = 1; while (i < 10) { // 循环体 i ++; };
do while
循环是js
中惟一的一种后测试的循环,它包括两个部分:循环体和后侧条件。记住:在一个do while
循环中,循环体至少会运行一次,后测条件决定循环体是否再次运行。编程语言
Javascriptvar i = 1; do { // 循环体 } while (i++ < 10)
for in
循环有一个很是特殊的用途:能够枚举任何对象的命名函数属性。函数
Javascriptfor (var attr in object) { // 循环体 };
每一次循环,属性都会被对象的属性的名字(一个字符串)填充,直到全部的对象属性遍历完才会返回。返回的属性包括对象的使实例属性和对象从原型链基础来的属性。性能
想要提升循环性能,第一步选用哪一种循环。在这四个循环里面,for in
循环执行的速度都比其余三个循环要慢。学习
大部分状况下咱们都不会采用for in
循环,可是其余的循环类型性能都至关,难以肯定哪一种循环执行速度更快。选择循环类型应该基于需求而不是性能。
能够经过设计for
和while
循环来完成特定动做的重复性操做。从3个目标来分析如何正确的选用for
和while
循环。
语义角度比较
for
和while
循环能够按照下面的模式来进行互相的转换。
Javascriptfor (initialization; test; increment) // 声明而且初始化循环变量,循环条件,递增循环变量 statements // 可执行的循环语句
至关于:
Javascriptinitialization // 声明而且初始化循环变量 while (test) { // 循环条件 statements // 可执行的循环语句 increment // 递增循环变量 }
for
循环是以循环变量的变化来控制循环进程的,即for
循环流程是预先计划好的,虽然中途可能会因存在异常状况或特别状况而退出循环,可是循环的规律是有章可循的。这样的话就方便预知循环的次数和每次循环的状态信息等等。
while
循环根据特定条件来决定循环操做,因为条件是动态的,没法预知条件几时是true
或者false
,所以该循环操做就具备很大的不肯定性,每一次循环时都不知道下一次循环状态如何,只能经过条件的变化来肯定。
因此for
循环一般用于有规律的重复操做中。while
循环一般用于特定条件的重复操做,以及依据特定事件控制的循环等操做。
思惟模式角度比较
for
循环和while
循环在思惟模式上也存在差别。
for
循环中,将循环的三个要素(起始值、终止值和步长)定义为3个基本表达式做为结构语法的一部分固定在for
语句里面,使用小括号;
进行语法分隔,这样有利于js
的进行快速预编译。
在阅读到for
循环结构的第一行代码的时候,就可以获取到整个循环结构的控制方式,而后再根据上面的表达式来决定是否执行循环体内的语句。
Javascriptfor (var i = 0; i < 10; i++) { alert(i); };
能够按照下面的逻辑思惟进行总结:
1 < i < 10
、步长为i++
。alert(i);
。这种把循环操做的环境条件和循环操做语句分离开的设计可以提升程序的执行效率,同时可以避免由于把循环条件与循环语句混合在一块儿而形成的错误。
在for
循环的特异性致使在执行复杂的条件时效率会大大的下降。相对而言,while
循环就比较适合运http://naotu.baidu.com/viewshare.html?shareId=auuohz8fwm8k的条件,它将复杂的循环控制放在循环体内执行,而while
语句自身仅用于测试循环条件,这样就避免告终构的分隔和逻辑的跳跃。
Javascriptvar a = true, b = 1; while (a) { // 在循环体内间接计算迭代 if (9 < b) { a = false; } alert(b); b++; }
从达到目标的角度比较
有一些循环的循环次数在循环以前就能够先预测,如计算1到100的数字和。而有一些循环具备不可预测性们没法事前肯定循环的次数,甚至没法预知循环操做的趋向,这些构成了在设计循环结构时候必须考虑的达成目标须要解决的问题,即便是相同的操做,若是达到的目标的角度不一样,可能重复了操做的设计也就不一样。
许多复杂的算法都是经过比较容易实现的递归实现。如阶乘函数。
Javascriptfunction factorial(n) { if (0 === n) { return 1; } else { return n * factorial(n - 1); } };
递归函数的问题:错误定义或者缺乏终结条件会致使函数运行时间过长,使浏览器出现假死现象。递归函数还会受到浏览器调用栈的大小的限制。
在ES6中js
拥有了尾递归优化,详情请看迎接ECMAScript 6, 使用尾递归
能够经过递归函数实现的算法均可以经过迭代来实现。迭代算法一般包括几个不一样的循环,分别对应算法过程当中的不一样方面。虽然迭代也会致使性能问题,可是使用优化的循环就能够代替长时间运行的递归函数,能够提升新能,由于运行一个循环比反复调用一个函数的开销要小。
使用迭代来实现合并排序算法:
Javascriptfunction merge(left, right) { var result = []; while (left.length > 0 && right.length > 0) { if (left[0] < right[0]) { result.push(left.shift()); } else { result.push(right.shift()); } } return result.concat(left).concat(right); }; function mergeSort(items) { if (items.length === 1) { return items; } var work = []; for (var i = 0, len = items.length; i < len; i++) { work.push(items[i]); }; work.push([]); for (var lim = len; lim > 1; lim = (lim + 1) / 2) { for (var j = 0, k = 0; k < lim; j++, k += 2) { work[j] = merge(work[k], work[k + 1]); } work[j] = []; }; return work[0]; };
循环结构是最浪费资源的一种流程。循环结构中的一点小的损耗都会被放大,从而影响程序运行的效率。
优化结构
循环结构经常是与分支结构混合在一块儿,因此如何嵌套也就很是的讲究。例如,设计一个循环结构,结构内的循环语句只有在特定的条件下才被执行,
Javascriptvar a = true; for (var i = 0; i < 10; i++) { if (a) {} //条件判断 };
在这个循环里面,if
语句会被反复的运行,若是这个if
语句是一个固定的条件检测表达式,若是if
的条件不会受到循环结构的影响,那么用下面这种结构设计会更加复合:
Javascriptif (a) { for (var i = 0; i < 10; i++) { }; }
可是if
条件表达式受循环结构的制约,那就不能使用这种结构嵌套了。
避免没必要要的重复操做
在循环里面常常会存在一些没必要要的损耗。下面一个例子:
Javascriptfor (var i = 0; i < 10; i++) { var a= [1,2,3,4,5,6,7,8,9,10]; alert(a[i]); };
在这个循环里面,每循环一次就会在定义一个新的数组,很明显这是一个重复的操做,把数组放到循环体外面会更加的高效:
Javascriptvar a= [1,2,3,4,5,6,7,8,9,10]; for (var i = 0; i < 10; i++) { alert(a[i]); };
妥善定义循环变量
对于for
循环来讲,它主要利用循环变量来控制整个结构的运行。当循环变量仅用于结构内部的时候,不妨在for
语句外面定义循环的变量,这样也能够优化循环结构。
最后,若是文章有什么错误和疑问的地方,请指出。与sf各位共勉!