[TOC]
# **流程控制**
  流程控制語句是區分編程語言和非編程語言的標志。流程控制語句可以控制代碼的執行流程或順序,JavaScript中的流程控制結構有三種,分別是順序結構,分支結構,循環結構。
<br>
## **順序結構**
  從上到下執行的代碼就是順序結構,程序默認就是由上到下順序執行的,如圖:
順序結構流程圖

<br>
<br>
## **分支結構**
分支結構流程圖

<br>
### **if 語句**
  if 語句作用:根據判斷條件的結果(true或false),來決定執行哪一塊代碼。可分為以下三種結構。
<br>
1. **if 語句,如果 if 條件表達式成立,則執行分支體**
**語法格式:**
>[success] // 如果...那么...
> if (/* 條件表達式 */) {
> // 分支體 語句
> }
  需求:定義一個用于變量存儲數值,判斷這個變量是否是偶數
```
var num = 8;
if (num % 2 === 0) {
console.log('偶數:' + num);
}
```
<br>
2. **if else,如果 if 條件表達式不成立,則執行else分支體**
>[success] //如果...那么... 否則...
> if (/* 條件表達式 */){
> // if分支體 語句
> } else {
> // else分支體 語句
> }
  需求:定義一個變量存儲數值,判斷這個變量是偶數還是奇數
```
//能被2整除的是偶數,否則是奇數
var num = 1;
if (num % 2 === 0) {
console.log(num + ' 是偶數');
} else {
console.log(num + ' 是奇數');
}
```
<br>
3. 在**if-else if-else** 結構中,程序從上到下執行,如果某個表達式成立就執行該分支體語句,否則繼續往下執行其他分支語句的判斷,一旦執行了某個分支體語句,執行完畢該分支語句后,就結束整個 if-else if -else結構,若整個結構中沒有成立的條件,則執行最后的else分支體。跟if-else相似,if-else if-else最后總會執行一個分支語句。
```
//如果...那么...否則如果...那么...
if (/* 條件1 */){
// 分支體 語句
} else if(/* 條件2 */){
// 分支體 語句
} else if(/* 條件3 */){
// 分支體 語句
} else {
// 最后默認分支體 語句
}
```
<br>
  需求:分數轉換,把百分制轉換成等級 ABCDE,等級劃分規則如下:
分數大于100則輸出提示 '不在分數范圍內!' ;
分數屬于 \[ 90, 100 \],則輸出 'A' ;
分數屬于 \[ 80, 90),則輸出 'B' ;
分數屬于\[ 70, 80 ) ,則輸出 'C' ;
分數屬于 \[ 60, 70 ) ,則輸出 'D' ;
分數小于60則輸出 'E' ;
```
//寫法一
var score = 6;
if (score > 100) {
console.log('不在分數范圍內');
}else if (score >= 90 && score <= 100) {
console.log('A');
}else if (score >= 80 && score < 90) {
console.log('B');
}else if (score >= 70 && score < 80) {
console.log('C');
}else if (score >= 60 && score < 70) {
console.log('D');
}else {
console.log('E');
}
//寫法二:簡化后(推薦)
if (score > 100) {
console.log('不在等級范圍內');
} else if (score >= 90) {
console.log('A');
} else if (score >= 80) {
console.log('B');
} else if (score >= 70) {
console.log('C');
} else if (score >= 60) {
console.log('D');
} else {
console.log('E');
```
<br>
### **三元運算符**
  三元運算符是具有三個操作數的運算符,三元運算符又叫三目運算符,JavaScript中只有一種三元運算符。當if-else語句要返回一個結果時,可以使用三元運算符替換。
  格式如下:
>[success]
>表達式1 ? 表達式2 : 表達式3
>是對if……else語句的一種簡化寫法
>三元運算符中的操作數是一個表達式的運算結果,該結果是布爾類型,運算過程為:
>如果表達式1結果為true,則返回表達式2的結果;
>否則(表達式1結果為false)返回表達式3的結果。三元運算符又稱三目運算符。
需求:
1. 定義一個變量存儲年齡,判斷這個年齡是否滿18歲
```
var age = 16;
//console.log(age >= 18 ? '成年' : '未成年');
var result = age >= 18 ? '成年' : '未成年';
console.log(result);
```
2. 定義兩個變量存儲數值,求這兩個數中的最大值
```
var num1 = 8;
var num2 = 6;
var max = num1 > num2 ? num1 : num2;
console.log(max);
```
<br>
### **switch語句**
  switch是分支結構的一種語句,它是通過判斷表達式的結果是否等于case語句的常量,來執行相應的分支體的。與if語句不同的是,switch語句有以下兩個特點:
1. switch語句只能做值的相等判斷,而if語句可以做值的范圍判斷;?
2. switch語句做值的相等判斷時,使用全等運算符 ===;
3. 在實際開發中,if語句可以代替switch語句。
>[success] switch (表達式) {
> case 常量1:
> [語句;]
> [break;]
> [case 常量2:]
> [語句;]
> [break;]
> ...
> [case 常量n:]
> [語句;]
> [break;]
> [default:]
> [語句;]
> [break;]
> }
  需求:定義一個變量存儲星期,使用switch語句判斷變量的值是星期幾,并輸出對應的星期。
```
var day = 7;
switch (day) {
case 1:
console.log('星期一');
break;//跳出switch分支結構
case 2:
console.log('星期二');
break;
case 3:
console.log('星期三');
break;//跳出switch分支結構
case 4:
console.log('星期四');
break;
case 5:
console.log('星期五');
break;//跳出switch分支結構
case 6:
console.log('星期六');
break;
case 7:
console.log('星期日');
break;
default:
console.log('不在星期范圍內');
}
//注意:switch語句在判斷值相等的時候,使用的是全等運算符(即 ===),全等運算符要求變量的值和類型都相等才相等。
```
<br>
### **布爾類型的隱式轉換**
  流程控制語句會把括號中的表達式的值隱式轉換(自動轉換)成布爾類型,然后才使用轉換后的結果作判斷。除了流程控制語句的表達式,一元運算符 "!" 也會將值隱式轉換成布爾類型。
```
//1、在流程控制中使用的隱式轉換
var num = 0;
if(num){ //做了隱式轉換
console.log(num);
}
//2、在運算符中的隱式轉換
var str = '';
var isRight = !!str;
console.log(isRight);
```
>[info]注意五種特例:0,' ',NaN,undefined,null,轉換成布爾類型的結果都是false。
<br>
<br>
## **循環結構**
  在JavaScript中,循環是指重復地做一件事情,JavaScript中的循環語句有三種,while循環語句、do-while循環語句和for循環語句。

<br>
### **while語句**
  while語句執行流程圖

  語法格式:
>[success] // 當循環條件為true時,執行循環體,
> // 當循環條件為false時,結束循環。
> while (循環條件) {
> //循環體
> }
注意:開發中避免死循環!
```
var bool = 1;
while (bool){
console.log('死循環');
}
```
需求
1、編寫while循環代碼,輸出1-100之間的所有整數
~~~
var num = 1;
while (num<=100){
? ?console.log(num);
? ?//num增加1
? ?//num = num + 1;
? ?// num += 1;
? ?num++ ;
}
~~~
2、編寫while循環代碼,計算1-100之間的所有整數和需求分析: (1)定義兩個變量,一個存儲所有整數,一個存儲所有整數和,如 num,sum (2)在循環中把每個整數加到整數和變量中
~~~
var num = 1;
var sum = 0;
while (num <= 100) {
? ?// sum = sum + num;
? ?sum += num;
? ?num++ ;
}
console.log(sum)//5050
~~~
3、編寫while循環代碼,輸出100以內 3 的倍數(課堂練習)
~~~
//定義num變量用于記錄循環次數
var num = 0;
while (num <= 100) {
? ?//判斷該數值是否是3的倍數(求余)
? ?if (num % 3 === 0) {
? ? ? ?console.log(num);
? }
? ?//num自身加1
? ?num++ ;
}
~~~
4、編寫while循環代碼,輸出100以內所有偶數需求分析: (1)判斷所有整數是否是偶數,如果是偶數,則輸出
~~~
//定義num變量用于記錄循環次數
var num = 0;
while (num <= 100) {
? ?//判斷該數值是否能被2整除(求余)
? ?if (num % 2 === 0) {
? ? ? ?console.log(num);
? }
? ?//num自身加1
? ?num++ ;
}
~~~
5、編寫while循環代碼,輸出100以內所有偶數的和需求分析: (1)在while循環中判斷一個數是否是偶數,獲取到100以內的所有偶數 (2)將所有偶數累加到一個變量中
~~~
var num = 0;//定義num變量用于記錄循環次數
var sum = 0;//定義sum變量用于記錄數值的和
while (num < 100) {
? ?//判斷該數值是否能被2整除(求余)
? ?if (num % 2 === 0) {
? ? ? ?sum += num;
? }
? ?//num自身加1
? ?num++ ;
}
console.log(sum);
~~~
<br>
### **do-while語句**
  do-while循環和while循環非常像,二者經常可以相互替代,但是do-while的特點是不管條件成不成立,do循環體都會先執行一次。
do-while執行流程圖

  語法格式:
```
do {
// 循環體;
} while (循環條件);
```
  需求:
1、 編寫do-while循環代碼,計算1-100之間的整數和
~~~
//初始化變量
var num = 1;
var sum = 0;
do{//循環體
? ?sum += num;//累加求和
? ?num++ ;//自增
}while (num <= 100);//循環條件
console.log(sum);//輸出
~~~
2、 編寫do-while循環代碼,求100以內所有7的倍數的和(課堂練習)
~~~
var num = 1;//循環參數
var sum = 0;//累加結果
do{//循環體
? ?if (num % 7 === 0) {//判斷是否是7的倍數:% (取余)
? ? ? ?sum += num;//累加操作
? }
? ?num++ ;//自增
}while (num <= 100);//循環條件
console.log(sum);
~~~
3、 編寫do-while循環代碼,循環輸出 '可不可以,和你在一起?',并提示用戶輸入 '可以/不可以',如果用戶輸入的值不是'可以' ,則繼續循環。否則彈出 '我們就別再分離'。
~~~
do{
//prompt() 方法用于顯示可提示用戶進行輸入的對話框。
? ?var inStr = prompt('可不可以,和你在一起?', '永遠在一起!(可以/不可以)');
? ?console.log(inStr);
}while (inStr != '可以');
alert('我們就別再分離!');
~~~
<br>
### **for語句**
  JavaScript的循環結構中,除了while和do-while循環,還有for循環。**while和do-while一般用于循環次數不確定的情況,for循環一般用于循環次數確定的情況。**
<br>
  for循環執行流程圖

  語法格式:
>[success]// for循環括號中表達式之間是用";"號分隔的,千萬不要寫成","
for (初始化表達式1; 條件表達式2; 自增表達式3) {
// 循環體4
}
**執行順序(記住)**:1243 --> 243 --> 243 --> 2......,直到條件表達式 返回 false 就停止循環。編寫for循環代碼,輸出1-100之間的所有整數。

  需求:
1、編寫for循環代碼,求1-100之間所有數的和
~~~
var sum = 0;//定義和變量
for (var i = 0; i <= 100; i++) {//1:步長,每次加1
? ?sum += i;//累加操作
}
console.log(sum);//5050
~~~
2、編寫for循環代碼,求1-100之間所有整數和的平均值
思路:先求和,后取平均值
~~~
var sum = 0;
for (var i = 0; i <= 100; i++) {
? ?sum += i;//累加求和
}
console.log(sum/100);
~~~
3、編寫for循環代碼,求1-100之間所有偶數的和
~~~
var sum = 0;
for (var i = 0; i <= 100; i++) {
? ?if (i % 2 === 0) {//對2取余
? ? ? ?sum += i;
? }
}
console.log(sum);
~~~
4、編寫for循環代碼,同時求1-100之間所有偶數和奇數的和(課堂練習)
思路:定義兩個變量,一個用于存儲奇數和,一個用于存儲偶數和。
~~~
var oddSum = 0;//奇數和
var evenSum = 0;//偶數和
for (var i = 0; i <= 100; i++) {
? ?if (i % 2 === 0) {
? ? ? ?//偶數
? ? ? ?evenSum += i;
? }else{
? ? ? ?//奇數
? ? ? ?oddSum += i;
? }
}
console.log('偶數和為:'+evenSum);
console.log('奇數和為:'+oddSum);
~~~
<br>
### **嵌套for循環**
  在之前學習的for循環中,我們解決問題是:重復執行某一個操作。如果一個重復的操作需要做N次,此時得使用嵌套循環。
  語法格式:
>[success]for (初始化表達式1; 條件表達式2; 自增表達式3) {
// 循環體
for (初始化表達式1; 條件表達式2; 自增表達式3) {
// 循環體
}
}
  需求:
1、編寫for循環代碼,輸出10\*10的正方形
在瀏覽器控制臺輸出星號是,發現星號疊加起來了,為了解決這個問題,我們引入一個str變量,用于暫存星號,循環結束后再把str變量輸出即可。

~~~
// 定義一個變量,用于存儲 *
var start = '';
// 重復地做for循環操作
for (var j = 0; j < 10; j++) { // 拼接 * 的行數
? ?// 拼接星號
? ?for (var i = 0; i < 10; i++) { // 拼接 * 的個數
? ? ? ?start = start + '* ';
? }
? ?// 換行
? ?start = start + '\n';
}
console.log(start);
~~~
2、編寫for循環代碼,輸出直角三角形
輸出三角形和輸出正方形的相似,不同的是三角形每行的列數逐行遞減。也就是說,三角形每行輸出的星號個數是變化的,因此我們可以在內層循環中,控制星號個數的變量應該逐行減1來實現。

~~~
//定義一個變量,用于存儲 *
var start = '';
//執行十次 '拼接*的行' 操作
for (var j = 10; j > 0; j--) { // '拼接*的行' 操作
? ?// j -> 10 9 8 7 6 5 4 3 2 1 0
? ?for (var i = 0; i < j; i++) { // 拼接*的個數
? ? ? ?start = start + '* ';
? }
? ?// 換行
? ?start = start + '\n';
}
console.log(start);
~~~
3、編寫for循環代碼,輸出九九乘法表(課后練習)
思路:九九乘法表跟直角三角形的形狀是一樣的,不同的是,九九乘法表要利用數值相乘,所以循環變量要從1開始,循環中可以使用制表符 \\t 分隔每個等式。

~~~
var start = '';
for (var j = 1; j < 10; j++) {//外層循環:控制行的輸出
? ?for (var i = j; i < 10; i++) {//內層循環:控制列的輸出
? ? ? ?start += j+'*'+i +'='+(j * i)+'\t';//累加*和空格
? }
? ?start += '\n';//累加換行
}
console.log(start);
~~~
### **continue和break**
  break:立即跳出當前整個循環(注意:如果是多層循環,則跳出當前層循環),即循環結束,開始執行循環后面的代碼(直接跳到大括號)
  continue:立即跳出當前(本次)循環,繼續下一次循環(跳到i++的地方)
  需求:
1、求整數20-200之間,第一個能被17整除的數。
使用break終止循環
~~~
var sum = 0;
for (var i = 20; i <= 200; i++) {
? ?if (i % 17 === 0) {
? ? ? ?console.log(i)
? ? ? ?//使用break終止循環
? ? ? ?break;
? }
}
~~~
>[info] 注意:如果break寫在二重循環的內循環中,則當執行break語句時,內循環終止(結束),代碼繼續往后執行,如果執行的是外循環,外循環又會開啟內循環的執行,所以又會再執行內循環的代碼,知道外循環執行結束,才往后繼續執行。
2、求整數20~200的累加值,但要求跳過所有個位為7的數
使用continue跳過循環
```
var sum = 0;
for (var i = 20; i <= 200; i++) {
if (i % 10 === 7) {
//使用continue跳過循環
continue;
}
sum += i;
}
console.log(sum)
```
*****
<br>
# JavaScript變量
## 什么是變量
  變量是計算機內存中存儲數據的標識符,根據變量名稱可以獲取到內存中存儲的數據。
  在日常生活中,有些東西是固定不變的,有些東西則會發生變化。例如,人的姓名和生日是固定不變的,但心情和年齡卻會隨著時間變化而變化。人們把那些會發生變化的東西稱為變量。
  當程序需要將值保存起來以備將來使用時,便將其賦值給一個變量。變量(variable)是一個用于保存值的占位符,可以通過變量名稱來獲得對值的引用。
標識符(Identifier)就是一個名字,用來對變量、函數、屬性、參數進行命名,或者用做某些循環語句中的跳轉位置的標記。

使用目的:使用變量可以方便地存儲、獲取、修改、刪除內存中的數據。
*****
## 變量的命名規則和規范
**規則**:必須遵守的,不遵守會報錯
1. 由字母、數字、下劃線、$符號組成,不能以數字開頭;
2. 不能是關鍵字和保留字,例如:var、if、for,enum
3. 區分大小寫

**規范**:建議遵守的,不遵守不會報錯
1. 變量名具有意義。可顧名思義,例如age、name;
2. 遵守匈牙利命名法、駝峰命名法和帕斯卡命名法。
駝峰命名法:第一個單詞首字母小寫,后面單詞的首字母需要大寫。例如:userName、userPassword;
### 匈牙利命名法
  引用于[http://www.w3cplus.com/javascript/variable-naming-principles.html](http://www.w3cplus.com/javascript/variable-naming-principles.html)
[匈牙利命名法](https://zh.wikipedia.org/wiki/%E5%8C%88%E7%89%99%E5%88%A9%E5%91%BD%E5%90%8D%E6%B3%95)匈牙利命名法是電腦程序設計中的一種變量命名規則,此命名法又可細分為:系統匈牙利命名法和匈牙利應用命名法。
  匈牙利命名法具備語言獨立的特性,并且首次在BCPL語言中被大量使用。由于BCPL只有機器字這一種數據類型,因此這種語言本身無法幫助程序員來記住變量的類型。匈牙利命名法通過明確每個變量的數據類型來解決這個問題。
  在匈牙利命名法中,一個變量名由一個或多個小寫字母開始,這些字母有助于記憶變量的類型和用途,緊跟著的就是程序員選擇的任何名稱。這個后半部分的首字母可以大寫,以區別前面的類型指示字母。
匈牙利命名法:
>[success]變量名=數據類型+對象描述
* **數據類型**:指點是JavaScript中六種數據類型之一,`undefined`、`null`、`boolean`、`number`、`string`和`Object`
* **對象描述**:指對象名字全稱或名字的一部分,而且要有明確含義,易記而且還要好理解
  有ES6之后,數據的類型不再是六種了,其新增加了Symbol這個新數據類型,有關于Symbol的相關介紹,可以閱讀這篇文章《[深入解析ES6: Symbol](http://www.w3cplus.com/javascript/es6-in-depth-symbols.html)》。
先來看個示例
~~~
var aPerson = []; // Array數組
var oBtn = document.getElementById('btn'); //Object對象
var fnName = function () {}; // function函數
var sName = "w3cplus"; // string字符串
~~~
  如上面的示例中的變量名稱`aPerson`、`oBtn`、`fnName`或者`sName`。每個變量名前都有代表數據類型的對應字母,然后后面緊跟有意義的單個單詞名多個單詞,并且單詞的字母都大寫(其實這種方法,稱之為駝峰寫法,后面會介紹)。
JavaScript變量名中代表數據類型都有對應的字線,如下所示:
* **`s`**: 表示字符串String
* **`i`**: 表示整型Int(它是Number中的整數類型)
* **`fl`**: 表示浮點Float(它是Number中的小數類型)
* **`b`**: 表示布爾Boolean
* **`a`**: 表示數組Array
* **`o`**: 表示對象Object
* **`fn`**: 不示函數Function
* **`re`**: 表示正則Regular Expression
有關于匈牙利命名更多的細節可以[點擊這里](https://zh.wikipedia.org/wiki/%E5%8C%88%E7%89%99%E5%88%A9%E5%91%BD%E5%90%8D%E6%B3%95)閱讀。
<br>
### 駝峰命名法
  當變量名和函數名稱是由二個或多個單字鏈接在一起,而構成的唯一識別字時,利用“駝峰式大小寫”來表示,可以增加變量和函數的可讀性。
  “駝峰式大小寫(Camel-Case)一詞來自Perl語言中普遍使用的大小寫混合格式,而Larry Wall等人所著的暢銷書《Programming Perl》(O'Reilly出版)的封面圖片正是一匹駱駝。”
  “駝峰式大小寫”命名規則可視為一種慣例,并無絕對與強制,為的是增加識別和可讀性。一旦選用或設置好命名規則,在程序編寫時應保持一致格式。
駝峰命名法常見有兩種格式:
* **小駝峰式命名法(lower camel case)**:第一個單詞以小寫字母開始;第二個單詞的首字母大寫,例如:`firstName`、`lastName`。
* **大駝峰式命名法(upper camel case)**:每一個單詞的首字母都采用大寫字母,例如:`FirstName`、`LastName`、`CamelCase`,也被稱為[Pascal命名法](https://zh.wikipedia.org/wiki/Pascal%E5%91%BD%E5%90%8D%E6%B3%95)。
有關于駝峰式命名方法更多的介紹,可以[點擊這里](https://zh.wikipedia.org/wiki/%E9%A7%9D%E5%B3%B0%E5%BC%8F%E5%A4%A7%E5%B0%8F%E5%AF%AB)閱讀。
<br>
### 帕斯卡命名法
  Pascal命名法(Pascal Case,巴斯卡命名法/帕斯卡命名法),電腦程序編寫時的一套命名規則(慣例)。
  當變量名和函數名稱是由二個或二個以上單字鏈接在一起,而構成的唯一識別字時,用以增加變量和函數的可讀性。
  單字之間不以空格斷開或連接號(`-`)、下劃線(`_`)鏈接,第一個單前綴字母采用大寫字母;后續單字的首字母亦用大寫字母,例如:`FirstName`、`LastName`。每一個單字的首字母都采用大寫字母的命名格式,被稱為“Pascal命名法”,源自于Pascal語言的命名慣例,也有人稱之為“大駝峰式命名法”(Upper Camel Case),為駝峰式大小寫的子集。
  “Pascal命名法”可視為一種命名慣例,并無絕對與強制,為的是增加識別和可讀性。一旦選用或設置好命名規則,在程序編寫時應保持格式的一致性。
  有關于帕斯卡命名法更詳細的介紹可以[點擊這里](https://zh.wikipedia.org/wiki/%E5%B8%95%E6%96%AF%E5%8D%A1%E5%91%BD%E5%90%8D%E6%B3%95)閱讀。
  雖然上面三種方法在JavaScript中命名變量常見的方法,也是很多規范推薦使用的命名方法;但除此之外還有別的方法。比如說變量名有兩個或多個單詞時,可以在多個單詞間使用`-`或`_`連接起來。如`first-name`或者說`first_name`。
*****
<br>
## 變量的使用
  在使用變量之前,首先要把變量定義出來,JavaScript中,定義變量分為“聲明變量”和“變量賦值”兩個步驟。
### 語法格式
>[success] //定義變量
> var 變量名; //變量聲明
> 變量名 = 變量值; //變量賦值
>
> var 變量名 = 變量值; //變量的聲明與賦值
>
> 例:
> 需求:聲明一個變量,用于存儲年齡,然后給這個變量賦值
> var age;
> age = 18;
> console.log(age); //輸出到控制臺
>
> 或者
> var age = 18; //直接聲明并賦值
> console.log(age); //輸出到控制臺
### 實際應用
#### 例1
需求:使用臨時變量作為輔助,交換兩個變量的值
>[info] 需求分析:
> 1. 定義定義三個變量,兩個用于存儲數據,一個作為臨時變量。如 num1, num2, temp ;
> 2. 使用臨時變量輔助,先完成一個變量值的交換。如 temp = num1, num1 = num2 ;
> 3. 最后完成另一個變量值的交換
```
var num1 = 5; //聲明num1賦值為5
var num2 = 6; //聲明num2賦值為6
var temp; //聲明變量把
temp = num1; //把num1的值賦值給temp,此時temp=5;
num1 = num2; //把num2的值賦值給num1,此時num1=6;
num2 =temp; //把temp的值賦值給num1,此時num2=5;
console.log(num1,num2);
```
#### 例2
需求:不使用臨時變量,交換兩個數值變量的值
>[info] 需求分析:
> 兩個變量的交換公式,如 a, b
> a = a + b;
> b = a - b;
> a = a - b;
```
var num3 = 3; //聲明num3賦值為3
var num4 = 4; //聲明num4賦值為4
num3 = num3 + num4; //把num3和num4的和賦值給num3,此時num3=7
num4 = num3 - num4; //把num3減num4的差賦值給num4,此時num4=3
num3 = num3 - num4; //把num3減num4的差賦值給num3,此時num3=4
console.log(num3, num4);//
*/
```