for 語句
for 語句是循環(huán)語句中的一種。
for 語句可以使程序在某一個(gè)條件下重復(fù)執(zhí)行一段代碼。
1. 基本語法
for 語句相對(duì)于 if 語句稍微復(fù)雜,通常為以下格式:
for (初始語句; 條件; 條件為真值時(shí)執(zhí)行的語句) {
// 循環(huán)體
}
初始語句
會(huì)在循環(huán)開始前進(jìn)行執(zhí)行。
條件
會(huì)在每次循環(huán)結(jié)束后執(zhí)行,結(jié)果影響循環(huán)語句是否要繼續(xù)執(zhí)行。
條件為真時(shí)執(zhí)行的語句
通常會(huì)用來影響下一次計(jì)算條件的結(jié)果。
2. 為什么需要循環(huán)語句
循環(huán)的應(yīng)用非常廣泛,如果有學(xué)習(xí)過數(shù)據(jù)結(jié)構(gòu)與算法,會(huì)發(fā)現(xiàn)大部分的算法都需要循環(huán)介入,否則會(huì)使程序變得冗余復(fù)雜。
如我們需要生成一段 HTML 列表代碼:
<div id="container"></div>
<script>
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
var li1 = '<li>' + arr[0] + '</li>';
var li2 = '<li>' + arr[1] + '</li>';
var li3 = '<li>' + arr[2] + '</li>';
var li4 = '<li>' + arr[3] + '</li>';
var li5 = '<li>' + arr[4] + '</li>';
var li6 = '<li>' + arr[5] + '</li>';
var li7 = '<li>' + arr[6] + '</li>';
var li8 = '<li>' + arr[7] + '</li>';
var li9 = '<li>' + arr[8] + '</li>';
var ul = '<ul>'+ li1 + li2 + li3 + li4 + li5 + li6 + li7 + li8 + li9 + '</ul>';
document.getElementById('container').innerHTML = ul;
</script>
可以發(fā)現(xiàn)這里生成列表的代碼很冗余,都是重復(fù)的操作,如果使用 for 循環(huán),代碼可以改成這樣:
<div id="container"></div>
<script>
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
var lis = '';
// 單獨(dú)拿到數(shù)組的長度
var len = arr.length;
// 聲明變量i用來計(jì)數(shù)
var i;
for (i = 0; i < len; i++) {
lis = lis + ('<li>' + arr[i] + '</li>');
}
var ul = '<ul>' + lis + '</ul>';
document.getElementById('container').innerHTML = ul;
</script>
這里使用 for 循環(huán)生成了一個(gè)列表,效果和上述聲明九個(gè)變量然后做拼接的方式是一樣的。
循環(huán)開始前先聲明的變量i
用于計(jì)數(shù),表示當(dāng)前循環(huán)到第幾次。
在循環(huán)開始前先將i
設(shè)置為0,這只會(huì)執(zhí)行一次,隨后比較當(dāng)前循環(huán)的次數(shù)是否小于數(shù)組長度,如果比數(shù)組長度小則執(zhí)行i++
,i++
會(huì)先使用i
的值,再做累加 ( i = i + 1) 操作,隨后執(zhí)行循環(huán)體,重復(fù)上述操作。
具體的流程如下:
len 的值為 9
- 第一次循環(huán)
- i 的值為 0,i是小于 len 變量的,所以 arr[0] 的值就是 1,這個(gè)時(shí)候 lis 被累加了
<li>1</li>
。
- i 的值為 0,i是小于 len 變量的,所以 arr[0] 的值就是 1,這個(gè)時(shí)候 lis 被累加了
- 第二次循環(huán)
- i的值為 1,i 是小于 len 變量的,所以 arr[1] 的值就是 2,這個(gè)時(shí)候 lis 被累加了
<li>2</li>
。
- i的值為 1,i 是小于 len 變量的,所以 arr[1] 的值就是 2,這個(gè)時(shí)候 lis 被累加了
- 第三次循環(huán)
- i 的值為 2,i 是小于 len 變量的,所以 arr[2] 的值就是 3,這個(gè)時(shí)候 lis 被累加了
<li>3</li>
。
- i 的值為 2,i 是小于 len 變量的,所以 arr[2] 的值就是 3,這個(gè)時(shí)候 lis 被累加了
- 第四次循環(huán)
- i 的值為 3,i是小于 len 變量的,所以 arr[3] 的值就是 4,這個(gè)時(shí)候 lis 被累加了
<li>4</li>
。
- i 的值為 3,i是小于 len 變量的,所以 arr[3] 的值就是 4,這個(gè)時(shí)候 lis 被累加了
- 第五次循環(huán)
- i的值為 4,i 是小于 len 變量的,所以arr[4]的值就是5,這個(gè)時(shí)候lis被累加了
<li>5</li>
。
- i的值為 4,i 是小于 len 變量的,所以arr[4]的值就是5,這個(gè)時(shí)候lis被累加了
- 第六次循環(huán)
- i的值為 5,i 是小于 len 變量的,所以 arr[5] 的值就是 6,這個(gè)時(shí)候 lis 被累加了
<li>6</li>
。
- i的值為 5,i 是小于 len 變量的,所以 arr[5] 的值就是 6,這個(gè)時(shí)候 lis 被累加了
- 第七次循環(huán)
- i的值為 6,i 是小于 len 變量的,所以 arr[6] 的值就是 7,這個(gè)時(shí)候 lis 被累加了
<li>7</li>
。
- i的值為 6,i 是小于 len 變量的,所以 arr[6] 的值就是 7,這個(gè)時(shí)候 lis 被累加了
- 第八次循環(huán)
- i 的值為 7,i 是小于 len 變量的,所以 arr[7] 的值就是 8,這個(gè)時(shí)候 lis 被累加了
<li>8</li>
。
- i 的值為 7,i 是小于 len 變量的,所以 arr[7] 的值就是 8,這個(gè)時(shí)候 lis 被累加了
- 第九次循環(huán)
- i的值為 8,i 是小于 len 變量的,所以 arr[8] 的值就是 9,這個(gè)時(shí)候 lis 被累加了
<li>9</li>
。
- i的值為 8,i 是小于 len 變量的,所以 arr[8] 的值就是 9,這個(gè)時(shí)候 lis 被累加了
- 第十次循環(huán)
- i 的值為 9,i 等于 len 變量,不再小于 len,條件不成立,循環(huán)結(jié)束。
雖然流程看起來復(fù)雜,但是代碼的可維護(hù)性得到了提高,冗余代碼也減少了,如果這個(gè)時(shí)候li
標(biāo)簽需要加一些屬性,如class
或者style
,只需要修改循環(huán)體中的一行代碼即可。
這種形式的 for 循環(huán)還有一種語法:
for (初始語句; 條件; 條件為真值時(shí)執(zhí)行的語句) 需要循環(huán)的語句;
和 if 語句很像,這種屬于行循環(huán)語句,這種用到的比較少,因?yàn)榇a的可閱讀性比較低,而且一般用到循環(huán)的場景都不止一行代碼。
3. for … in
for…in 循環(huán)可以用來遍歷對(duì)象的屬性名。
var obj = {
name: '小紅',
age: 12,
hobby: ['打籃球', '唱歌'],
};
for (key in obj) {
console.log(obj[key]);
}
// 輸出:
// "小紅"
// 12
// ["打籃球", "唱歌"]
每一次遍歷拿到的 key 就是對(duì)象的某一個(gè)屬性名,當(dāng)屬性名被遍歷完后會(huì)自動(dòng)退出循環(huán)。
有部分 key 是無法遍歷到的,具體規(guī)則可以參閱對(duì)象章節(jié)。
4. 無限循環(huán)
for (;;) {
console.log('loop...');
}
這樣的循環(huán)語句會(huì)陷入無限循環(huán)。
大部分無限循環(huán)會(huì)讓瀏覽器卡死,需要強(qiáng)制退出瀏覽器!
5. 循環(huán)應(yīng)用的例子
5.1 判斷一個(gè)數(shù)是不是質(zhì)數(shù)
var num = 17;
var flag = false;
var len;
var i;
for (i = 2, len = 17 -1; i <= len; i++) {
if (num % i === 0) {
flag = true;
break; // break可以中斷循環(huán)
}
}
if (flag) {
console.log(num + '不是質(zhì)數(shù)');
} else {
console.log(num + '是質(zhì)數(shù)');
}
// 輸出:"17是質(zhì)數(shù)"
首先要知道什么是質(zhì)數(shù),質(zhì)數(shù)就是只能被1和本身整除的數(shù)。
所以如果要判斷num
是不是質(zhì)數(shù),只需要去掉頭尾,從2
循環(huán)到num - 1
,用num
對(duì)每一個(gè)循環(huán)數(shù)做取余操作,如果存在余數(shù)為 0 的,就說明中間有個(gè)數(shù)可以被整除,那就不是質(zhì)數(shù),反之就是質(zhì)數(shù)。
5.2 計(jì)算階乘
var num = 4;
var result = 1;
var i;
for (i = num; i > 1; i--) {
result = result * i;
}
console.log(result); // 輸出:24
階乘是所有小于及等于某一數(shù)的正整數(shù)的積,如4的階乘,在數(shù)學(xué)中表示為4!
,結(jié)果為4 * 3 * 2 * 1
。
在代碼中,就可以用一個(gè)變量來保存每次做乘法的結(jié)果,如 4 的階乘,就可以用變量result
記錄結(jié)果,初始值為 1,循環(huán)可以從 4 循環(huán)到 1,每次將循環(huán)到的值乘以result
,循環(huán)結(jié)束后就可以得到結(jié)果。
6. 小結(jié)
循環(huán)語句和條件語句一樣,是給語言帶來處理業(yè)務(wù)能力的重要特性之一。
通常如果需要連續(xù)執(zhí)行多次的重復(fù)操作,都應(yīng)該考慮使用循環(huán)來解決。