javascript for循环从入门到偏门(效率优化+奇特用法)


Posted in Javascript onAugust 01, 2012

一,for循环的基本写法
代码如下:

//例一for(var i=1;i<=10;i++) { 
alert(i); 
}

这段代码太简单了,我都不好意思拿出手。代码的执行结果是依次弹出1到10,PS:在早期的IE如IE6中,你把10改成10000,就能让用户一直点确定什么也不能干了哈哈——不要说是我出的主意。
由于这是一篇基础课程,所以我们回归正题来详细分析一下这段代码吧。
for循环的结构都是类似的,任意一个for循环都是这样的:
for(开始前;循环进行的条件;循环一次结束后做什么) {
// 主体代码
}如果仔细看一下for循环,就会发现他的一个万年不变的特点:for后的()中,永远是有且只有两个;(英文分号)!
上面的结构代码已经说明,分号的作用是用来分割for循环的执行条件。这些条件都是缺一不可的,可以为空,但位置必须留着,所以必须有两个;。
开始前:一般用来声明一些变量,如例一的var i=0,就像准备了一个篓子,里面暂时没有任何东西。工具的数量不限,你可以在for循环开始前声明100个变量,除了不好看之外,也没什么问题。
循环进行的条件:如第1个例子中的i<10,就是条件了,只有条件为真时,for循环才会进行下去,例一的条件可以看成if(i<10){//do...}。可以想象成篓子最多装10个东西,如果多了10个,就不装了,退出循环。
循环一次后做什么:例一中只是简单的给篓子里面加入一个东西,其实你还可以做很多事,毕竟循环一次不容易。
特别说明:for循环“开始前”的代码只会执行一次,不会影响整个for循环的效率,而“进行条件”与“一次结束后做什么”,你循环次数有多少,他就执行多少次,所以他们经常成为for循环性能瓶颈。
如果说for循环第1个;前是开始前做的事,那我可不可以把开始前的事情拿到for循环前面来呢?只要在开始前定义就行了嘛。答案是可以:
//例2 
var i=0; 
for(;i<10;i++) { 
alert(i); 
}

但要注意,虽然for后面的括号里“开始前”已经没有内容了,但;(分号)还在!而且必须在!
同理,既然第2个;后面的代码是一次结束后执行的,那我也可以把要执行的放在for循环后啊。如下:
//例子3 
var i=0; 
for(;i<10;) { 
alert(i); 
i++ 
}

但依然,万恶的两个;还是必须存在。
上面也就是两个基础的“偏门用法”了。。。不要说我坑爹
不过你也看到了,执行循环的条件,是不能单独提出来的,必须放在两个分号之间!前后夹击!
二,for循环的偏门写法
1,我们把例一的代码变成:
var i=0;
for(;i<10;alert(i++)) ;怎么样?这才是坑爹啊,{}都没有了!不过完全正确啊!
不过这种写法太过逆天,第2个;后面的代码最好不要多,一多起来你就不能掌握i的值了,而且因为代码混乱可能导致人为的语法错误。
适用环境:
简单的for循环操作,比如造一个元素依次是从1到1000的数字的这么一个数组,就用这招,酷就一个字。
2,深入分析
通过前面的例子我们知道,其实for循环的执行条件就是判断一个布尔值,就像这样:
var t = true; 
if(t == true) { 
alert('啊!') 
}

这个if语句没人看不懂吧,其实还可以这样写:
var t = true; 
if(t) { 
alert('啊!') 
}

效果是一样的,如果for循环的进行条件就是判断布尔值,那下面这种写法理解起来就不困难了:
var i = 10; 
for(;i;i--){ 
alert(i); 
}

这段代码的效果是依次弹出10到1(和例一反过来了)。其中for循环的进行条件简单的要死,就是个i.但根据我们前面的解说,其实条件是这样的:
if(i) { 
//do 
}

也就是i为真的情况,就继续执行循环。这个for循环的i什么时候为真呢,只要i不等于0,空字符串,undefined,null,false时,就都为真。
所以此for循环一直会执行,直到i=0,就结束了。但我们代码中不会看到0 ,迷惑新手,装B利器。
3,又一个
先看代码,来自园友snandy:
var ary = ["jack","tom","lily","andy"]; 
for(var i=0,a;a=ary[i++];){ 
console.log(a); 
}

依然是注意看for循环的进行条件:a=ary[i++]。特别注意这里是=而不是==,要是==的话循环就没法进行了。
这个条件判断很扯,我也比较晕。类似于:
if(a=b) {...} //注意是=!
此时如果b是false,那就会返回false了。
回到上面的例子中,如果i++加出了头,那ary[i++]就是false值了(null,undefined都算),所以条件就成了false,所以循环就断了。
这个例子局限很大,snandy也提到了,比如你数组中就是有个0,那也可能会导致循环终结。
4,jQuery的一个写法
function sibling( elem ) { 
var r = [], 
n = elem.parentNode.firstChild; 
for ( ; n; n = n.nextSibling ) { 
if ( n.nodeType === 1 && n !== elem ) { 
r.push( n ); 
} 
} 
return r; 
}

这是从jquery里提取的获得兄弟节点的办法,他有一个奇特的for循环。循环进行的条件是判断n是否为真。由于n一直是一个html节点,所以一直为真。而每次循环结束后都会把n的下一个节点赋给n,而当n的下一个节点没有时,n就成了false,终结循环。
小结:
从上面所有的例子可以看到,任他千奇百怪的for循环,都离不开两个;。大家想看懂一个for循环的原理,直接以;为界线分割for循环即可,一目了然。
三,for循环的效率优化
1,缓存变量
这也是最常用的效率优化办法:
var arr =[1,2,23,...,1000]; 
for(var i=0,l = arr.length;i<l;i++) { 
// 
}

由于执行条件每次循环都要判断,所以如果每次循环都从arr中读取length的话,无疑很浪费而且必然增加计算次数,造成效率浪费。
2,倒序法
比如一个数组有1000个元素,如果不考虑提取顺序,那么可以倒序循环:
var arr =[1,2,23,...,1000]; 
var i = arr.length; 
for(;i>0;i--){ 
//alert(i); 
}

为什么倒序会比顺序效率快?没有科学道理啊!其实只是因为倒序可以少用一个变量(对比下上一个例子吧),除开这点,两者没有速度差别。
3,注意跳出
不进行不必要的操作,这是基本逻辑。如有1000个li里面,有一个li上有个特殊的className,我们要找出这个li。那么,由于已经确定只有一个这样的li,我们找到这个li就应该马上跳出,break,下面的循环就没必要进行了。这样一来,由于li有999/1000的几率不是最后一个,我们肯定能节约不少计算。
其他情况请举一反三。
4,使用偏门用法
上面我介绍的偏门用法不只是写出来好看的,大部分都有节约变量节约计算的效果,能用就用,既酷又有效,何乐而不为呢?
----------------------------总结--------------------------------
我喜欢Javascript的灵活,不仅仅是因为可以用来装酷。希望在博客园学到更多的JS知识,大牛们的文章我经常看,收益良多。下面是一些我找到的在园子里的牛人,不全,没有列出来者不要诅咒我。
cloudgamer,司徒正美,汤姆大叔,snandy以及其他太低调的高手。想找他们的博客直接搜索吧。
PS:实在是喜欢博客园的插入代码功能,以后涉及到大量代码的文章都直接发博客园吧。
不要尝试下面的代码:
var arr =[1,2,23,1000]; 
for(var i=0,l = arr.length;i<l;) { 
if(arr[i]>10000) { 
i++; 
} 
}
Javascript 相关文章推荐
js 模拟气泡屏保效果代码
Jul 10 Javascript
在一个js文件里远程调用jquery.js会在ie8下的一个奇怪问题
Nov 28 Javascript
遍历DOM对象内的元素属性示例代码
Feb 08 Javascript
js兼容火狐获取图片宽和高的方法
May 21 Javascript
Javascript中的getUTCDay()方法使用详解
Jun 10 Javascript
JS特效实现图片自动播放并可控的效果
Jul 31 Javascript
跟我学习javascript解决异步编程异常方案
Nov 23 Javascript
JQ选择器_选择同类元素的第N个子元素的实现方法
Sep 08 Javascript
Node学习记录之cluster模块
May 31 Javascript
JavaScript如何对图片进行黑白化
Apr 10 Javascript
js中自定义react数据验证组件实例详解
Oct 19 Javascript
解决axios会发送两次请求,有个OPTIONS请求的问题
Oct 25 Javascript
jQuery源码中的chunker 正则过滤符分析
Jul 31 #Javascript
关于jquery ajax 调用带参数的webservice返回XML数据一个小细节
Jul 31 #Javascript
基于jquery的点击链接插入链接内容的代码
Jul 31 #Javascript
基于jQuery实现的百度导航li拖放排列效果,即时更新数据库
Jul 31 #Javascript
基于jQuery的动态增删改查表格信息,可左键/右键提示(原创自Zjmainstay)
Jul 31 #Javascript
jQuery.each()用法分享
Jul 31 #Javascript
artDialog 4.1.5 Dreamweaver代码提示/补全插件 附下载
Jul 31 #Javascript
You might like
蝙蝠侠:侠影之谜
2020/03/04 欧美动漫
不用iconv库的gb2312与utf-8的互换函数
2006/10/09 PHP
用PHP和ACCESS写聊天室(四)
2006/10/09 PHP
php桌面中心(四) 数据显示
2007/03/11 PHP
php addslashes 函数详细分析说明
2009/06/23 PHP
PHP中is_file不能替代file_exists的理由
2014/03/04 PHP
PHP基于php_imagick_st-Q8.dll实现JPG合成GIF图片的方法
2014/07/11 PHP
Yii调试查看执行SQL语句的方法
2016/07/15 PHP
php lcg_value与mt_rand生成0~1随机小数的效果对比分析
2017/04/05 PHP
图片放大镜jquery.jqzoom.js使用实例附放大镜图标
2014/06/19 Javascript
javascript中typeof操作符和constucor属性检测
2015/02/26 Javascript
Bootstrap表单组件教程详解
2016/04/26 Javascript
jQuery中借助deferred来请求及判断AJAX加载的实例讲解
2016/05/24 Javascript
微信小程序  网络请求API详解
2016/10/25 Javascript
Webpack实现按需打包Lodash的几种方法详解
2017/05/08 Javascript
js 只比较时间大小的实例
2017/10/26 Javascript
Vue实现动态创建和删除数据的方法
2018/03/17 Javascript
angular 数据绑定之[]和{{}}的区别
2018/09/25 Javascript
Vue动态路由缓存不相互影响的解决办法
2019/02/19 Javascript
构建大型 Vue.js 项目的10条建议(小结)
2019/11/14 Javascript
Python日期操作学习笔记
2008/10/07 Python
Python多线程和队列操作实例
2015/06/21 Python
使用python加密自己的密码
2015/08/04 Python
Python对数据库操作
2016/03/28 Python
Python 多进程和数据传递的理解
2017/10/09 Python
python tensorflow学习之识别单张图片的实现的示例
2018/02/09 Python
python opencv判断图像是否为空的实例
2019/01/26 Python
Python数据类型之String字符串实例详解
2019/05/08 Python
Python实现Wordcloud生成词云图的示例
2020/03/30 Python
eBay英国购物网站:eBay.co.uk
2019/06/19 全球购物
马来西亚排名第一的宠物用品店:Pets Wonderland
2020/04/16 全球购物
Servlet都有哪些方法?主要作用是什么?
2014/03/04 面试题
运动会跳远加油稿
2014/02/20 职场文书
大学生职业生涯十年规划书范文
2014/09/17 职场文书
协议书范文
2015/01/27 职场文书
2019终止劳动合同协议书最新范本!
2019/07/09 职场文书