owned this note
owned this note
Published
Linked with GitHub
# <font class="h2">迴圈</font>
###### tags: `javascript`
<style>
.h2 {
background: linear-gradient(135deg,#fff,#537479) ;
color: #537479;
display:block;
padding: 6px 5px;
border-radius: 4px;
}
.h3 {
background: linear-gradient(180deg,#fff 50%,#c9d5d4) ;
color: #537479;
display:block;
padding: 6px 5px;
border-bottom: 3px solid #537479;
}
.h4 {
color: #537479;
font-weight:bold;
font-size:1.1em;
}
</style>
<br>
迴圈(Loop)就是讓一段程式碼重複執行好幾次,而數值會依次數有「遞增」或「遞減」的變化來完成退出的條件,減少重複撰寫很多行相同程式碼的情況。
<br><br>
### <font class="h3">for迴圈</font>
:::info
**格式說明**
```javascript
for(初始值;條件判斷;結束時執行的動作){迴圈要執行內容};
```
「變數初始值」通常用i命名
:::
**範例:**
```javascirpt
for (var i=0;i<10 ;i++){
console.log(i);
}//1,2,3,4,5,6,7,8,9
```
`i`的值會從0開始,慢慢加1遞增,直到它變成10,而導致條件判斷i<10不成立後終止整個迴圈。
<br>
### <font class="h4">➤搭配陣列</font>
可用陣列長度來做條件判斷
```javascirpt
var array = ["frist","second","thrid"];
for (var i=0;i<array.length ;i=i+1){
console.log(array[i])
}//frist,second,thrid
```
<br>
**範例:**
篩選農場組人
```javascript
var farms = [
{
farmer:"Casper",
field:6
},{
farmer:"Charlie",
field:10
}
]
var farmsTotal = farms.length;
for(var i =0; i<farmsTotal;i++){
console.log("第"+(i+1)+"個農場主人是"+farms[i].farmer);
}//第1個農場主人是Casper,第2個農場主人是Charlie
```
### <font class="h4">➤搭配if</font>
篩選出超過100隻小雞的農場
```javascript
var farms = [
{
farmer:"Casper",
field:6,
chick:200
},{
farmer:"Charlie",
field:10,
chick:50
},{
farmer:"John",
field:6,
chick:120
}
]
var farmsTotal = farms.length;
for(var i=0;i<farmsTotal;i++){
if(farms[i].chick>100){
console.log(farms[i].farmer+"的小雞超過100隻以上");
}
}//Casper的小雞超過100隻以上,John的小雞超過100隻以上
```
<br>
### <font class="h4">➤加總</font>
計算今年的香蕉採收總數
```javascript
var farms = [
{
farmer:"Casper",
field:6,
chick:200,
banana:5000
},{
farmer:"Charlie",
field:10,
chick:50,
banana:1000
},{
farmer:"John",
field:6,
chick:120,
banana:3215
}
]
var farmsTotal = farms.length;
var bananaTotal =0;
for(var i=0; i<farmsTotal;i++){
bananaTotal+=farms[i].banana;
}
console.log("今年村子的香蕉採收量"+bananaTotal)
```
<br><br><br><br>
### <font class="h4">➤for迴圈不要使用匿名函式</font>

<br><br><br><br>
### <font class="h3">while迴圈</font>
只要在某條件成立的情況下,都會重複執行這段程式碼
:::info
**格式說明**
```javascript
while(條件判斷){
//迴圈要執行內容
}
```
通常使用`while`迴圈時,會利用在迴圈以外的值來做迴圈的條件的判斷,
然後再迴圈內再去改變這個值得內容。
:::
**範例:**
```javascirpt
var i =0;
while(i<10){
console.log(i);
i++;
}//1,2,3,4,5,6,7,8,9
```
<br><br><br><br>
### <font class="h3">break、continue運用</font>
那麼假如我們想要跳過其中幾次,或是想要提早離開迴圈
### <font class="h4">➤break直接跳離迴圈</font>
有個陣列,假設裡面包含一堆 0 與若干其他數字,而我們不知道裡面內容。
我們想要找出不是「0」的「第一個數字」是哪一個:
```javascript
var arr = [0,0,0,0,7,0,9,0,4,8,0];
for(var i = 0; i < arr.length; i++ ) {
if( arr[i] !== 0 ){
console.log( arr[i] );
break;// 找到那個不是 0 的數字,印出後退出迴圈
}
}//7
```
<br>
### <font class="h4">➤continue會跳過繼續下一次迴圈</font>
假設我們想要印出 1 ~ 10 的所有數字,但跳過 3 的倍數
```javascript
for (var i = 1; i <= 10; i++) {
if( i % 3 === 0){
continue;
} // i 能被 3 整除表示 i 是 3 的倍數,遇到 continue 就會跳過這次
console.log(i);
}//1,2,4,5,7,8,10
```
<br>
### <font class="h4">➤label標記</font>
Javascript中標籤(label)是一個識別符號。標籤可以與變數重名,它是一個獨立的語法元素(既不是變數,也不是型別)
label可以和 break 或 continue 搭配使用。標記就是在一條陳述式前面加個可以引用的識別符號。
```javascript
let str = '';
loop1:
for (let i = 0; i < 5; i++) {
if (i === 1) {
continue loop1;
}
str = str + i;
}
console.log(str);//0234
```
`loop1`可以自訂義取名
<br><br><br><br>
### <font class="h3">無限迴圈</font>
不管 `for` 或 `while` 迴圈,「結束的條件」是很重要的。
在執行迴圈的時候,若是「執行條件」沒有設定好,很容易變成「無窮迴圈」在裡面無限空轉
範例:
```javascript
for (var i = 0; i >= 0; i++) {
console.log(i);
}
// i 不管怎麼樣都會大於等於 0
```
<br>
```javascript
var i = 1;
while ( i <= 10 ){
console.log( i );
}
// 結束迴圈時, i 的值仍然是 1
```
<br><br><br><br>
### <font class="h3">for迴圈非同步的問題</font>
### let與var的問題
```javascript
for(var i = 0;i<5;i++){
window.setTimeout(function(){
console.log(i)
},1000)
} //5 5 5 5 5
```
對非同步程式設計有所瞭解的可能都知道==setTimeout裡的callback會在event loop的佇列裡堆積,直到`i++`操作完成==。所以打印出兩個2。而這裡需要注意的是var i變數。因為沒有任何函式封裝,所以i將成為全域性變數。
```javascript
for(let i = 0;i<5;i++){
window.setTimeout(function(){
console.log(i)
},i*1000)
} //0 1 2 3 4
```
當var被修改成let時,情況發生了改變。程式執行結果是1~4。
首先需要認識到let和var在作用域上的差別。var被圈定在函式內,而let被圈定在任何有中括號的範圍內。雖然上圖的for迴圈沒有將i圈定在中括號內,但ES6仍然在此機制上給let設定了屬於自己的作用域。
<br><br>
### 也可以使用立即函式
這邊使用==閉包==的觀念,立即函式帶入了參數,會行程區塊作用域,i變數會被緩存
```javascript
for (var i = 0; i < 5; i++) {
(function(i) {
window.setTimeout(function () {
console.log(i)
}, i*1000)
})(i)
} //0 1 2 3 4
```
### 也可以使用setTtimeout傳入第三個參數形成閉包
```javascript
for (var i = 0; i < 5; i++) {
window.setTimeout(function (i) {
console.log(i)
}, i*1000,i)
} //0 1 2 3 4
```
<br><br><br><br>
### <font class="h3">for 與 while 兩者的差異點</font>
`for`迴圈比較適合依序存取值得狀況,一開始就知道要執行幾次。
`while`比較適合用在不確定迴圈會執行幾次的情況。
<br>
### <font class="h3">for 迴圈與 forEach 有什麼不同</font>
:arrow_right:[forEach](https://hackmd.io/@grayshine/SJBz5yFUF)
過去,當有一個陣列的內容需要依序取值時,都會使用 `for` 迴圈(for loop)的形式將值,
現在,陣列執行迴圈不像過去那麼麻煩,陣列的原型中增加了許多方法可以直接運用,其中的 `forEach` 基本上可以達到 `for`迴圈的所有需求(基本上用了 `forEach` 不太會再去使用 `for loop`)。
相同的結果,使用 `forEach` 後更容易被閱讀、理解。
不過實際上這兩者還是略有差異。
### <font class="h4">➤for loop 可能會產生全域變數</font>
因為 JS 作用域是屬於函式作用域,而 `for loop` 在執行時使用 `var`所建立的變數是屬於在區塊 ``{}`` 內,因此 `for loop` 運行時所定義的變數很常會是建立在 全域 的環境下。
```javascript
var array = ['小明', '杰倫', '漂亮阿姨', '小美']
for (var i = 0; i < array.length; i++) {
const item = array[i];
console.log(i, item);
}
console.log(i); // 4
```
相對來說 `forEach` 使用 callback function 就不容易踩到這個雷,不過 `for loop` 依然可以使用 ES6 的 `let`, `const` 來解決作用域的問題
```javascript
for (let i = 0; i < array.length; i++) {
const item = array[i];
console.log(i, item);
}
console.log(i) // 無法取得 i
```
<br>
### <font class="h4">➤for 可以被中斷</font>
雖然 `for loop` 目前的使用率較不如 `forEach`,不過它可中斷運行的方式在 `forEach` 中是沒有的,如果迴圈中有必要停止運行,就可以使用 `for loop` 搭配 `break`。
<br>
### <font class="h4">➤並非所有陣列都能使用 forEach</font>
JavaScript 中的陣列依據原型的不同,也有另一種分支稱為類陣列(array-like),類陣列中的原型方法與一般定義的陣列就有所不同,其中的方法就可能不包含 forEach。
函式中的 arguments 就屬於類陣列,它的方法就不包含 forEach 的方法,因此它無法直接運行 forEach。
https://wcc723.github.io/development/2020/10/05/js-for-loop-vs-for-each/
<br>
### <font class="h4">第三周主線第七題範例</font>
下方為台灣一間旅館的JSON資料
有一個客戶,在下週二平常日時段,將所有房型都訂了一間房
請透過程程式去計算他一共花了多少錢
:::spoiler for迴圈方法
```javascript
let roomDetail = {
"success": true,
"items": [
{
"id": "3Elqe8kfMxdZv5xFLV4OUeN6jhmxIvQSTyj4eTgIowfIRvF4rerA2Nuegzc2Rgwu",
"imageUrl": "https:\/\/images.unsplash.com\/photo-1551776235-dde6d482980b?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2134&q=80",
"normalDayPrice": 1380,
"holidayPrice": 1500,
"name": "Single Room"
},
{
"id": "g0mYhN6ignMz4VYW7eiWsXZN8DHolHzH8LuVmM6hq5h6BrrqrLMw4aJgHv7LZ3RQ",
"imageUrl": "https:\/\/images.unsplash.com\/photo-1564182379166-8fcfdda80151?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1951&q=80",
"normalDayPrice": 1899,
"holidayPrice": 2000,
"name": "Deluxe Single Room"
},
{
"id": "RA8NhExaXXZB7EODVALSDvFFQzj1JP0a4C1pwZ1acPaieRBwiWoCb0FE0KUbXaxg",
"imageUrl": "https:\/\/images.unsplash.com\/photo-1526913621366-a4583840d736?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1950&q=80",
"normalDayPrice": 2460,
"holidayPrice": 2500,
"name": "Double Room"
},
{
"id": "kICyWhZ5XsfI4n1d4gBOsDjIyIxNozwgmxYKyZpzi5pjLcU2Nl4RhiGrn6zaPuTJ",
"imageUrl": "https:\/\/images.unsplash.com\/photo-1519710889408-a67e1c7e0452?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2134&q=80",
"normalDayPrice": 2888,
"holidayPrice": 3000,
"name": "Deluxe Double Room"
},
{
"id": "VCxbQq1vLeUtxW781k9Dlq3mHBRNl5YP19Lhq8k5TbIr2BeH58gRpnNKGoEgkysz",
"imageUrl": "https:\/\/images.unsplash.com\/photo-1558976825-6b1b03a03719?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1950&q=80",
"normalDayPrice": 3350,
"holidayPrice": 3500,
"name": "Twin Room"
},
{
"id": "YovqNpFDaal598jbpd1A14gXwDE6gekTqJgxOAGcq78B8YnP7claymQVFy2GTwgb",
"imageUrl": "https:\/\/images.unsplash.com\/photo-1552902019-ebcd97aa9aa0?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2134&q=80",
"normalDayPrice": 3899,
"holidayPrice": 4000,
"name": "Deluxe Twin Room"
}
]
}
let totalcost = 0;
for (let i = 0; i < roomDetail.items.length; i++) {
totalcost += roomDetail.items[i].normalDayPrice
}
console.log(`客戶一共花了${totalcost}元`);
```
:::
:::spoiler forEach方法
```javascript
let roomDetail = {
"success": true,
"items": [
{
"id": "3Elqe8kfMxdZv5xFLV4OUeN6jhmxIvQSTyj4eTgIowfIRvF4rerA2Nuegzc2Rgwu",
"imageUrl": "https:\/\/images.unsplash.com\/photo-1551776235-dde6d482980b?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2134&q=80",
"normalDayPrice": 1380,
"holidayPrice": 1500,
"name": "Single Room"
},
{
"id": "g0mYhN6ignMz4VYW7eiWsXZN8DHolHzH8LuVmM6hq5h6BrrqrLMw4aJgHv7LZ3RQ",
"imageUrl": "https:\/\/images.unsplash.com\/photo-1564182379166-8fcfdda80151?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1951&q=80",
"normalDayPrice": 1899,
"holidayPrice": 2000,
"name": "Deluxe Single Room"
},
{
"id": "RA8NhExaXXZB7EODVALSDvFFQzj1JP0a4C1pwZ1acPaieRBwiWoCb0FE0KUbXaxg",
"imageUrl": "https:\/\/images.unsplash.com\/photo-1526913621366-a4583840d736?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1950&q=80",
"normalDayPrice": 2460,
"holidayPrice": 2500,
"name": "Double Room"
},
{
"id": "kICyWhZ5XsfI4n1d4gBOsDjIyIxNozwgmxYKyZpzi5pjLcU2Nl4RhiGrn6zaPuTJ",
"imageUrl": "https:\/\/images.unsplash.com\/photo-1519710889408-a67e1c7e0452?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2134&q=80",
"normalDayPrice": 2888,
"holidayPrice": 3000,
"name": "Deluxe Double Room"
},
{
"id": "VCxbQq1vLeUtxW781k9Dlq3mHBRNl5YP19Lhq8k5TbIr2BeH58gRpnNKGoEgkysz",
"imageUrl": "https:\/\/images.unsplash.com\/photo-1558976825-6b1b03a03719?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1950&q=80",
"normalDayPrice": 3350,
"holidayPrice": 3500,
"name": "Twin Room"
},
{
"id": "YovqNpFDaal598jbpd1A14gXwDE6gekTqJgxOAGcq78B8YnP7claymQVFy2GTwgb",
"imageUrl": "https:\/\/images.unsplash.com\/photo-1552902019-ebcd97aa9aa0?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2134&q=80",
"normalDayPrice": 3899,
"holidayPrice": 4000,
"name": "Deluxe Twin Room"
}
]
}
let bill = 0;
roomDetail.items.forEach(function(item){
bill += item.normalDayPrice;
});
console.log(`一共花了${bill}元`);
```
:::
<br>