网站首页 > 基础教程 正文
"懒"程序员才是好程序员。复制和粘贴样板代码,一但代码有错误,或代码功能修改,那么程序在修改的时候,程序员需要找到所有相同功能的代码一处处进行修改。这会使人重复发明轮子,而且在别人看代码的时候无法在更高层次都看待问题的解决方案。太容易陷入细节。
for循环
js中的for循环在进行一些细微变化时,可以引入不同的行为。编程的时候对于边界条件的判断往往会导致一些简单的错误。下面的一些for循环的细微变化导致边界条件的变化。
for(var i=0;i<=n;i++){...}
//包括最后的迭代
for(var i=1;i< n;i++){...}
//忽略第一次迭代
for(var i=n;i>=0;i--){...}
//包括第一次迭代
for(var i=n-1;i > 0;i++){...}
//忽略最后的迭代
在这里都是对终止条件的一个设置。这里可以有很多的方式,可以使终止条件发生错误。js的闭包是一种为这些模式建立迭代抽象方便的、富有表现力的手法,可以避免重复代码。
ES5中数组方法
其中ES5中提供的数组方法就包含很多。比如
Array.prototype.forEach
比如下面这段对数组的循环。
for(var i=0,n=players.length;i< n;i++){
players[i].score++;
}
使用数组的迭代方法,可以改写为
players.forEach(function(p){
p.score++;
});
上面的代码把循环的方式进行抽象,把要执行的具体代码通过函数传递闭包,完成对数组元素的操作及访问。这里消除了终止条件和任何数组索引。
Array.prototype.map
完成对数组的每个元素进行一些操作后建立一个新的数组。
使用循环
var trimmed=;
for(var i=0,n=input.length;i< n;i++){
trimmed.push(input[i].trim);
}
使用forEach
var trimmed=;
input.forEach(function(s){
trimmed.push(s.trim);
});
使用map
var trimmed=input.map(function(s){
return s.trim;
});
Array.prototype.filter
计算一个数组建立一个新数组,该数组只包含有数组的一些元素filter方法需要一个谓词函数,如果元素应该存在于新数组中则返回真值,如果元素应该被剔除则返回假值。例如,可以从价格表中提取出一个特定价格区间的列表。
listings.filter(function(listing){
return listing.price>=min&&listing.price<=max;
});
以上的forEach,map,filter三个方法都是ES5中,数组的默认方法。下面实现一个自己的迭代抽象。例:提取出满足谓词函数的数组的前几个元素,直到不满足的元素终止,不管后面是否有元素满足条件。
function takeWhile(a,pred){
var res=;
for(var i=0,n=a.length;i < n;i++){
if(!pred(a[i],i)){
break;
}
res[i]=a[i];
}
return res;
}
var prefix=takeWhile([1,2,3,4,26,18,9],function(n){
return n<10;
});
prefix;//[1, 2, 3, 4]
上面pred函数有两个参数,而下面的回调我们只传入了一个参数。对第二个参数没有进行处理,这里是无所谓的。
猴子补丁
把takeWhile函数添加到Array.prototype中使其成为一个方法。
Array.prototype.takeWhile=function(pred){
var res=;
for(var i=0,n=this.length;i < n;i++){
if(!pred(this[i],i)){
break;
}
res[i]=this[i];
}
return res;
};
var prefix=[1,2,3,4,26,18,9].takeWhile(function(n){
return n<10;
});
prefix;//[1, 2, 3, 4]
循环控制流操作
只有一点循环优于迭代,循环可以控制流操作,如break和continue。例如,使用forEach方法来实现takeWhile函数
function takeWhile(a,pred){
var res=;
a.forEach(function(x,i){
if(!pred(x)){
//?
}
res[i]=x;
});
return res;
}
上面的代码怎么终止该循环的当次执行。
内部异常
function takeWhile(a,pred){
var res=;
var earlyExit={};
try{
a.forEach(function(x,i){
if(!pred(x)){
throw earlyExit;
}
res[i]=x;
});
}catch(e){
if(e!==earlyExit){
throw e;
}
}
return res;
}
这样的处理方法,把原本简单的处理变得更加复杂了,不可取。
some,every
有没更简单的方法呢。下面看一下数组提供的用于提前终止循环的方法。some和every。
some方法返回一个布尔值表示其回调对数组的任何一个元素是否返回一个真值。
本人理解:
所有元素,对于传入的函数的判断,有一真则为真。全为假才为假。
相当于所有元素执行函数后取或。
[1,10,100].some(function(x){return x>5;});//true
[1,10,100].some(function(x){return x<0;});//false
every方法返回一个布尔值表示其回调函数是否对所有元素返回一个真值。
本人理解:
所有元素,对于传入的函数的判断,有一假则为假。全为真才为真。
相当于所有元素执行函数后取且。
[1,10,100].every(function(x){return x>5;});//false
[1,10,100].every(function(x){return x>0;});//true
这两个方法都是短路循环。只要产生的结果可以决定最后结果后,就不再执行后面的循环。即some一旦产生一个真值,则立即返回。every一旦产生一个假值,也立即返回。利用它们的特点,改写takeWhile函数。
function takeWhile(a,pred){
var res=;
a.every(function(x,i){
if(!pred(x)){
return false;//break
}
res[i]=x;
return true;
});
return res;
}
提示
-
使用迭代方法替换for循环使得代码可读,并且避免了重复循环控制逻辑
-
使用自定义的迭代函数来抽象未被标准库支持的常见循环模式
-
在需要提前终止循环的情况下,仍然推荐使用传统的循环。另外,some和every方法也可用于提前退出
- 上一篇: WPS宏(JSA)教程——循环语句for
- 下一篇: 有了 for 循环 为什么还要 forEach?
猜你喜欢
- 2025-01-02 Java for循环
- 2025-01-02 C语言for循环语句使用形式总结
- 2025-01-02 12.Java中的 for 循环
- 2025-01-02 VBA基本语法之For循环结构,都有什么含义,具体该怎么使用?
- 2025-01-02 实例 | 快速掌握200SMART FOR-NEXT指令使用技巧
- 2025-01-02 「绍棠」 vuejs中常用的js循环遍历对象的方法列举-案例
- 2025-01-02 C|代码优化:减少函数调用、内存引用,循环展开及提高并行度
- 2025-01-02 停止使用 .forEach:使用 for...of 循环改造你的代码
- 2025-01-02 LABVIEW学习笔记之for循环
- 2025-01-02 Java里的for循环怎么用
- 01-10AutoCAD命令大全, AutoCAD所有命令,AutoCAD命令集合
- 01-10资产管理如何做,用Excel vba,很简单,你还等什么
- 01-10除了Crontab,Swoole Timer也可以实现定时任务的
- 01-10PHP 安全的最佳实践
- 01-10通过天干地支计算对应五行
- 01-10PHP常用类 – 缓存类 cache
- 01-10php 一步步实现mvc架构——路由篇
- 01-10PHP类来实现一个数组,它将去除数组中所有值的头尾空格
- 最近发表
- 标签列表
-
- gitpush (61)
- pythonif (68)
- location.href (57)
- tail-f (57)
- pythonifelse (59)
- deletesql (62)
- c++模板 (62)
- css3动画 (57)
- c#event (59)
- linuxgzip (68)
- 字符串连接 (73)
- nginx配置文件详解 (61)
- html标签 (69)
- c++初始化列表 (64)
- exec命令 (59)
- canvasfilltext (58)
- mysqlinnodbmyisam区别 (63)
- arraylistadd (66)
- node教程 (59)
- console.table (62)
- c++time_t (58)
- phpcookie (58)
- mysqldatesub函数 (63)
- window10java环境变量设置 (66)
- c++虚函数和纯虚函数的区别 (66)