javascript for循環(huán)從入門到偏門(效率優(yōu)化+奇特用法)
更新時(shí)間:2012年08月01日 00:00:44 作者:
for循環(huán)是非?;A(chǔ)的javascript知識,但由于JS太靈活了,所以可能出現(xiàn)一些讓初學(xué)者崩潰的寫法。我決定由淺入深的解釋一下for循環(huán),算是給比我還新手的新手解惑吧,少走彎路
一,for循環(huán)的基本寫法
代碼如下:
//例一for(var i=1;i<=10;i++) {
alert(i);
}
這段代碼太簡單了,我都不好意思拿出手。代碼的執(zhí)行結(jié)果是依次彈出1到10,PS:在早期的IE如IE6中,你把10改成10000,就能讓用戶一直點(diǎn)確定什么也不能干了哈哈——不要說是我出的主意。
由于這是一篇基礎(chǔ)課程,所以我們回歸正題來詳細(xì)分析一下這段代碼吧。
for循環(huán)的結(jié)構(gòu)都是類似的,任意一個(gè)for循環(huán)都是這樣的:
for(開始前;循環(huán)進(jìn)行的條件;循環(huán)一次結(jié)束后做什么) {
// 主體代碼
}如果仔細(xì)看一下for循環(huán),就會發(fā)現(xiàn)他的一個(gè)萬年不變的特點(diǎn):for后的()中,永遠(yuǎn)是有且只有兩個(gè);(英文分號)!
上面的結(jié)構(gòu)代碼已經(jīng)說明,分號的作用是用來分割for循環(huán)的執(zhí)行條件。這些條件都是缺一不可的,可以為空,但位置必須留著,所以必須有兩個(gè);。
開始前:一般用來聲明一些變量,如例一的var i=0,就像準(zhǔn)備了一個(gè)簍子,里面暫時(shí)沒有任何東西。工具的數(shù)量不限,你可以在for循環(huán)開始前聲明100個(gè)變量,除了不好看之外,也沒什么問題。
循環(huán)進(jìn)行的條件:如第1個(gè)例子中的i<10,就是條件了,只有條件為真時(shí),for循環(huán)才會進(jìn)行下去,例一的條件可以看成if(i<10){//do...}??梢韵胂蟪珊t子最多裝10個(gè)東西,如果多了10個(gè),就不裝了,退出循環(huán)。
循環(huán)一次后做什么:例一中只是簡單的給簍子里面加入一個(gè)東西,其實(shí)你還可以做很多事,畢竟循環(huán)一次不容易。
特別說明:for循環(huán)“開始前”的代碼只會執(zhí)行一次,不會影響整個(gè)for循環(huán)的效率,而“進(jìn)行條件”與“一次結(jié)束后做什么”,你循環(huán)次數(shù)有多少,他就執(zhí)行多少次,所以他們經(jīng)常成為for循環(huán)性能瓶頸。
如果說for循環(huán)第1個(gè);前是開始前做的事,那我可不可以把開始前的事情拿到for循環(huán)前面來呢?只要在開始前定義就行了嘛。答案是可以:
//例2
var i=0;
for(;i<10;i++) {
alert(i);
}
但要注意,雖然for后面的括號里“開始前”已經(jīng)沒有內(nèi)容了,但;(分號)還在!而且必須在!
同理,既然第2個(gè);后面的代碼是一次結(jié)束后執(zhí)行的,那我也可以把要執(zhí)行的放在for循環(huán)后啊。如下:
//例子3
var i=0;
for(;i<10;) {
alert(i);
i++
}
但依然,萬惡的兩個(gè);還是必須存在。
上面也就是兩個(gè)基礎(chǔ)的“偏門用法”了。。。不要說我坑爹
不過你也看到了,執(zhí)行循環(huán)的條件,是不能單獨(dú)提出來的,必須放在兩個(gè)分號之間!前后夾擊!
二,for循環(huán)的偏門寫法
1,我們把例一的代碼變成:
var i=0;
for(;i<10;alert(i++)) ;怎么樣?這才是坑爹啊,{}都沒有了!不過完全正確??!
不過這種寫法太過逆天,第2個(gè);后面的代碼最好不要多,一多起來你就不能掌握i的值了,而且因?yàn)榇a混亂可能導(dǎo)致人為的語法錯(cuò)誤。
適用環(huán)境:
簡單的for循環(huán)操作,比如造一個(gè)元素依次是從1到1000的數(shù)字的這么一個(gè)數(shù)組,就用這招,酷就一個(gè)字。
2,深入分析
通過前面的例子我們知道,其實(shí)for循環(huán)的執(zhí)行條件就是判斷一個(gè)布爾值,就像這樣:
var t = true;
if(t == true) {
alert('??!')
}
這個(gè)if語句沒人看不懂吧,其實(shí)還可以這樣寫:
var t = true;
if(t) {
alert('??!')
}
效果是一樣的,如果for循環(huán)的進(jìn)行條件就是判斷布爾值,那下面這種寫法理解起來就不困難了:
var i = 10;
for(;i;i--){
alert(i);
}
這段代碼的效果是依次彈出10到1(和例一反過來了)。其中for循環(huán)的進(jìn)行條件簡單的要死,就是個(gè)i.但根據(jù)我們前面的解說,其實(shí)條件是這樣的:
if(i) {
//do
}
也就是i為真的情況,就繼續(xù)執(zhí)行循環(huán)。這個(gè)for循環(huán)的i什么時(shí)候?yàn)檎婺?,只要i不等于0,空字符串,undefined,null,false時(shí),就都為真。
所以此for循環(huán)一直會執(zhí)行,直到i=0,就結(jié)束了。但我們代碼中不會看到0 ,迷惑新手,裝B利器。
3,又一個(gè)
先看代碼,來自園友snandy:
var ary = ["jack","tom","lily","andy"];
for(var i=0,a;a=ary[i++];){
console.log(a);
}
依然是注意看for循環(huán)的進(jìn)行條件:a=ary[i++]。特別注意這里是=而不是==,要是==的話循環(huán)就沒法進(jìn)行了。
這個(gè)條件判斷很扯,我也比較暈。類似于:
if(a=b) {...} //注意是=!
此時(shí)如果b是false,那就會返回false了。
回到上面的例子中,如果i++加出了頭,那ary[i++]就是false值了(null,undefined都算),所以條件就成了false,所以循環(huán)就斷了。
這個(gè)例子局限很大,snandy也提到了,比如你數(shù)組中就是有個(gè)0,那也可能會導(dǎo)致循環(huán)終結(jié)。
4,jQuery的一個(gè)寫法
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里提取的獲得兄弟節(jié)點(diǎn)的辦法,他有一個(gè)奇特的for循環(huán)。循環(huán)進(jìn)行的條件是判斷n是否為真。由于n一直是一個(gè)html節(jié)點(diǎn),所以一直為真。而每次循環(huán)結(jié)束后都會把n的下一個(gè)節(jié)點(diǎn)賦給n,而當(dāng)n的下一個(gè)節(jié)點(diǎn)沒有時(shí),n就成了false,終結(jié)循環(huán)。
小結(jié):
從上面所有的例子可以看到,任他千奇百怪的for循環(huán),都離不開兩個(gè);。大家想看懂一個(gè)for循環(huán)的原理,直接以;為界線分割for循環(huán)即可,一目了然。
三,for循環(huán)的效率優(yōu)化
1,緩存變量
這也是最常用的效率優(yōu)化辦法:
var arr =[1,2,23,...,1000];
for(var i=0,l = arr.length;i<l;i++) {
//
}
由于執(zhí)行條件每次循環(huán)都要判斷,所以如果每次循環(huán)都從arr中讀取length的話,無疑很浪費(fèi)而且必然增加計(jì)算次數(shù),造成效率浪費(fèi)。
2,倒序法
比如一個(gè)數(shù)組有1000個(gè)元素,如果不考慮提取順序,那么可以倒序循環(huán):
var arr =[1,2,23,...,1000];
var i = arr.length;
for(;i>0;i--){
//alert(i);
}
為什么倒序會比順序效率快?沒有科學(xué)道理啊!其實(shí)只是因?yàn)榈剐蚩梢陨儆靡粋€(gè)變量(對比下上一個(gè)例子吧),除開這點(diǎn),兩者沒有速度差別。
3,注意跳出
不進(jìn)行不必要的操作,這是基本邏輯。如有1000個(gè)li里面,有一個(gè)li上有個(gè)特殊的className,我們要找出這個(gè)li。那么,由于已經(jīng)確定只有一個(gè)這樣的li,我們找到這個(gè)li就應(yīng)該馬上跳出,break,下面的循環(huán)就沒必要進(jìn)行了。這樣一來,由于li有999/1000的幾率不是最后一個(gè),我們肯定能節(jié)約不少計(jì)算。
其他情況請舉一反三。
4,使用偏門用法
上面我介紹的偏門用法不只是寫出來好看的,大部分都有節(jié)約變量節(jié)約計(jì)算的效果,能用就用,既酷又有效,何樂而不為呢?
----------------------------總結(jié)--------------------------------
我喜歡Javascript的靈活,不僅僅是因?yàn)榭梢杂脕硌b酷。希望在博客園學(xué)到更多的JS知識,大牛們的文章我經(jīng)常看,收益良多。下面是一些我找到的在園子里的牛人,不全,沒有列出來者不要詛咒我。
cloudgamer,司徒正美,湯姆大叔,snandy以及其他太低調(diào)的高手。想找他們的博客直接搜索吧。
PS:實(shí)在是喜歡博客園的插入代碼功能,以后涉及到大量代碼的文章都直接發(fā)博客園吧。
不要嘗試下面的代碼:
var arr =[1,2,23,1000];
for(var i=0,l = arr.length;i<l;) {
if(arr[i]>10000) {
i++;
}
}
代碼如下:
復(fù)制代碼 代碼如下:
//例一for(var i=1;i<=10;i++) {
alert(i);
}
這段代碼太簡單了,我都不好意思拿出手。代碼的執(zhí)行結(jié)果是依次彈出1到10,PS:在早期的IE如IE6中,你把10改成10000,就能讓用戶一直點(diǎn)確定什么也不能干了哈哈——不要說是我出的主意。
由于這是一篇基礎(chǔ)課程,所以我們回歸正題來詳細(xì)分析一下這段代碼吧。
for循環(huán)的結(jié)構(gòu)都是類似的,任意一個(gè)for循環(huán)都是這樣的:
for(開始前;循環(huán)進(jìn)行的條件;循環(huán)一次結(jié)束后做什么) {
// 主體代碼
}如果仔細(xì)看一下for循環(huán),就會發(fā)現(xiàn)他的一個(gè)萬年不變的特點(diǎn):for后的()中,永遠(yuǎn)是有且只有兩個(gè);(英文分號)!
上面的結(jié)構(gòu)代碼已經(jīng)說明,分號的作用是用來分割for循環(huán)的執(zhí)行條件。這些條件都是缺一不可的,可以為空,但位置必須留著,所以必須有兩個(gè);。
開始前:一般用來聲明一些變量,如例一的var i=0,就像準(zhǔn)備了一個(gè)簍子,里面暫時(shí)沒有任何東西。工具的數(shù)量不限,你可以在for循環(huán)開始前聲明100個(gè)變量,除了不好看之外,也沒什么問題。
循環(huán)進(jìn)行的條件:如第1個(gè)例子中的i<10,就是條件了,只有條件為真時(shí),for循環(huán)才會進(jìn)行下去,例一的條件可以看成if(i<10){//do...}??梢韵胂蟪珊t子最多裝10個(gè)東西,如果多了10個(gè),就不裝了,退出循環(huán)。
循環(huán)一次后做什么:例一中只是簡單的給簍子里面加入一個(gè)東西,其實(shí)你還可以做很多事,畢竟循環(huán)一次不容易。
特別說明:for循環(huán)“開始前”的代碼只會執(zhí)行一次,不會影響整個(gè)for循環(huán)的效率,而“進(jìn)行條件”與“一次結(jié)束后做什么”,你循環(huán)次數(shù)有多少,他就執(zhí)行多少次,所以他們經(jīng)常成為for循環(huán)性能瓶頸。
如果說for循環(huán)第1個(gè);前是開始前做的事,那我可不可以把開始前的事情拿到for循環(huán)前面來呢?只要在開始前定義就行了嘛。答案是可以:
復(fù)制代碼 代碼如下:
//例2
var i=0;
for(;i<10;i++) {
alert(i);
}
但要注意,雖然for后面的括號里“開始前”已經(jīng)沒有內(nèi)容了,但;(分號)還在!而且必須在!
同理,既然第2個(gè);后面的代碼是一次結(jié)束后執(zhí)行的,那我也可以把要執(zhí)行的放在for循環(huán)后啊。如下:
復(fù)制代碼 代碼如下:
//例子3
var i=0;
for(;i<10;) {
alert(i);
i++
}
但依然,萬惡的兩個(gè);還是必須存在。
上面也就是兩個(gè)基礎(chǔ)的“偏門用法”了。。。不要說我坑爹
不過你也看到了,執(zhí)行循環(huán)的條件,是不能單獨(dú)提出來的,必須放在兩個(gè)分號之間!前后夾擊!
二,for循環(huán)的偏門寫法
1,我們把例一的代碼變成:
var i=0;
for(;i<10;alert(i++)) ;怎么樣?這才是坑爹啊,{}都沒有了!不過完全正確??!
不過這種寫法太過逆天,第2個(gè);后面的代碼最好不要多,一多起來你就不能掌握i的值了,而且因?yàn)榇a混亂可能導(dǎo)致人為的語法錯(cuò)誤。
適用環(huán)境:
簡單的for循環(huán)操作,比如造一個(gè)元素依次是從1到1000的數(shù)字的這么一個(gè)數(shù)組,就用這招,酷就一個(gè)字。
2,深入分析
通過前面的例子我們知道,其實(shí)for循環(huán)的執(zhí)行條件就是判斷一個(gè)布爾值,就像這樣:
復(fù)制代碼 代碼如下:
var t = true;
if(t == true) {
alert('??!')
}
這個(gè)if語句沒人看不懂吧,其實(shí)還可以這樣寫:
復(fù)制代碼 代碼如下:
var t = true;
if(t) {
alert('??!')
}
效果是一樣的,如果for循環(huán)的進(jìn)行條件就是判斷布爾值,那下面這種寫法理解起來就不困難了:
復(fù)制代碼 代碼如下:
var i = 10;
for(;i;i--){
alert(i);
}
這段代碼的效果是依次彈出10到1(和例一反過來了)。其中for循環(huán)的進(jìn)行條件簡單的要死,就是個(gè)i.但根據(jù)我們前面的解說,其實(shí)條件是這樣的:
復(fù)制代碼 代碼如下:
if(i) {
//do
}
也就是i為真的情況,就繼續(xù)執(zhí)行循環(huán)。這個(gè)for循環(huán)的i什么時(shí)候?yàn)檎婺?,只要i不等于0,空字符串,undefined,null,false時(shí),就都為真。
所以此for循環(huán)一直會執(zhí)行,直到i=0,就結(jié)束了。但我們代碼中不會看到0 ,迷惑新手,裝B利器。
3,又一個(gè)
先看代碼,來自園友snandy:
復(fù)制代碼 代碼如下:
var ary = ["jack","tom","lily","andy"];
for(var i=0,a;a=ary[i++];){
console.log(a);
}
依然是注意看for循環(huán)的進(jìn)行條件:a=ary[i++]。特別注意這里是=而不是==,要是==的話循環(huán)就沒法進(jìn)行了。
這個(gè)條件判斷很扯,我也比較暈。類似于:
if(a=b) {...} //注意是=!
此時(shí)如果b是false,那就會返回false了。
回到上面的例子中,如果i++加出了頭,那ary[i++]就是false值了(null,undefined都算),所以條件就成了false,所以循環(huán)就斷了。
這個(gè)例子局限很大,snandy也提到了,比如你數(shù)組中就是有個(gè)0,那也可能會導(dǎo)致循環(huán)終結(jié)。
4,jQuery的一個(gè)寫法
復(fù)制代碼 代碼如下:
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里提取的獲得兄弟節(jié)點(diǎn)的辦法,他有一個(gè)奇特的for循環(huán)。循環(huán)進(jìn)行的條件是判斷n是否為真。由于n一直是一個(gè)html節(jié)點(diǎn),所以一直為真。而每次循環(huán)結(jié)束后都會把n的下一個(gè)節(jié)點(diǎn)賦給n,而當(dāng)n的下一個(gè)節(jié)點(diǎn)沒有時(shí),n就成了false,終結(jié)循環(huán)。
小結(jié):
從上面所有的例子可以看到,任他千奇百怪的for循環(huán),都離不開兩個(gè);。大家想看懂一個(gè)for循環(huán)的原理,直接以;為界線分割for循環(huán)即可,一目了然。
三,for循環(huán)的效率優(yōu)化
1,緩存變量
這也是最常用的效率優(yōu)化辦法:
復(fù)制代碼 代碼如下:
var arr =[1,2,23,...,1000];
for(var i=0,l = arr.length;i<l;i++) {
//
}
由于執(zhí)行條件每次循環(huán)都要判斷,所以如果每次循環(huán)都從arr中讀取length的話,無疑很浪費(fèi)而且必然增加計(jì)算次數(shù),造成效率浪費(fèi)。
2,倒序法
比如一個(gè)數(shù)組有1000個(gè)元素,如果不考慮提取順序,那么可以倒序循環(huán):
復(fù)制代碼 代碼如下:
var arr =[1,2,23,...,1000];
var i = arr.length;
for(;i>0;i--){
//alert(i);
}
為什么倒序會比順序效率快?沒有科學(xué)道理啊!其實(shí)只是因?yàn)榈剐蚩梢陨儆靡粋€(gè)變量(對比下上一個(gè)例子吧),除開這點(diǎn),兩者沒有速度差別。
3,注意跳出
不進(jìn)行不必要的操作,這是基本邏輯。如有1000個(gè)li里面,有一個(gè)li上有個(gè)特殊的className,我們要找出這個(gè)li。那么,由于已經(jīng)確定只有一個(gè)這樣的li,我們找到這個(gè)li就應(yīng)該馬上跳出,break,下面的循環(huán)就沒必要進(jìn)行了。這樣一來,由于li有999/1000的幾率不是最后一個(gè),我們肯定能節(jié)約不少計(jì)算。
其他情況請舉一反三。
4,使用偏門用法
上面我介紹的偏門用法不只是寫出來好看的,大部分都有節(jié)約變量節(jié)約計(jì)算的效果,能用就用,既酷又有效,何樂而不為呢?
----------------------------總結(jié)--------------------------------
我喜歡Javascript的靈活,不僅僅是因?yàn)榭梢杂脕硌b酷。希望在博客園學(xué)到更多的JS知識,大牛們的文章我經(jīng)常看,收益良多。下面是一些我找到的在園子里的牛人,不全,沒有列出來者不要詛咒我。
cloudgamer,司徒正美,湯姆大叔,snandy以及其他太低調(diào)的高手。想找他們的博客直接搜索吧。
PS:實(shí)在是喜歡博客園的插入代碼功能,以后涉及到大量代碼的文章都直接發(fā)博客園吧。
不要嘗試下面的代碼:
復(fù)制代碼 代碼如下:
var arr =[1,2,23,1000];
for(var i=0,l = arr.length;i<l;) {
if(arr[i]>10000) {
i++;
}
}
您可能感興趣的文章:
- javascript教程:關(guān)于if簡寫語句優(yōu)化的方法
- js中if語句的幾種優(yōu)化代碼寫法
- nodejs的10個(gè)性能優(yōu)化技巧
- JavaScript性能優(yōu)化之小知識總結(jié)
- js性能優(yōu)化 如何更快速加載你的JavaScript頁面
- JavaScript也談內(nèi)存優(yōu)化
- JavaScript定時(shí)器和優(yōu)化的取消定時(shí)器方法
- JS對img標(biāo)簽進(jìn)行優(yōu)化使用onerror顯示默認(rèn)圖像
- Uglifyjs(JS代碼優(yōu)化工具)入門 安裝使用
- 深入探究JavaScript中for循環(huán)的效率問題及相關(guān)優(yōu)化
- js 優(yōu)化次數(shù)過多的循環(huán) 考慮到性能問題
- 整理AngularJS框架使用過程當(dāng)中的一些性能優(yōu)化要點(diǎn)
- javascript定時(shí)器取消定時(shí)器及優(yōu)化方法
- JavaScript中對循環(huán)語句的優(yōu)化技巧深入探討
- JS代碼優(yōu)化技巧之通俗版(減少js體積)
- angularjs的一些優(yōu)化小技巧
- Extjs優(yōu)化(二)Form表單提交通用實(shí)現(xiàn)
- JS代碼優(yōu)化的8點(diǎn)建議
相關(guān)文章
JavaScript 瀏覽器兼容性總結(jié)及常用瀏覽器兼容性分析
本文是腳本之家小編日常整理些關(guān)于js兼容性問題,及IE與Firefox等常用瀏覽器的兼容性分析,對js瀏覽器兼容性相關(guān)知識感興趣的朋友一起學(xué)習(xí)吧2016-03-03淺談js構(gòu)造函數(shù)的方法與原型prototype
下面小編就為大家?guī)硪黄獪\談js構(gòu)造函數(shù)的方法與原型prototype。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-07-07javascript 大中小字體顯示實(shí)現(xiàn)代碼
有時(shí)候頁面中的正文一般都加上了字體大中小控制代碼,方便瀏覽者閱讀。2010-09-09淺析JavaScript的幾種Math函數(shù),random(),ceil(),round(),floor()
本文主要對JavaScript的幾種Math函數(shù),random(),ceil(),round(),floor()的作用進(jìn)行簡要解析,具有很好的參考價(jià)值,需要的朋友一起來看下吧2016-12-12JavaScript中數(shù)組雙重去重的方法總結(jié)
這篇文章主要為大家學(xué)習(xí)介紹了JavaScript中數(shù)組雙重去重的幾個(gè)常用方法,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-07-07JavaScript開發(fā)人員的10個(gè)關(guān)鍵習(xí)慣小結(jié)
還在一味沒有目的的編寫JavaScript代碼嗎?那么你就OUT了!讓我們一起來看看小編為大家搜羅的JavaScript開發(fā)人員應(yīng)該具備的十大關(guān)鍵習(xí)慣吧2014-12-12