[TOC]
# **流程控制**
  流程控制语句是区分编程语言和非编程语言的标志。流程控制语句可以控制代码的执行流程或顺序,JavaScript中的流程控制结构有三种,分别是顺序结构,分支结构,循环结构。
<br>
## **顺序结构**
  从上到下执行的代码就是顺序结构,程序默认就是由上到下顺序执行的,如图:
顺序结构流程图
![](images/顺序结构.png)
<br>
<br>
## **分支结构**
分支结构流程图
![](images/分支结构.png)
<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循环语句。
![](images/循环结构.png)
<br>
### **while语句**
  while语句执行流程图
![](images/while语句执行流程图.png)
  语法格式:
>[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执行流程图
![](images/dowhile执行流程图.png)
  语法格式:
```
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循环执行流程图
![](images/for循环执行流程图.png)
  语法格式:
>[success]// for循环括号中表达式之间是用";"号分隔的,千万不要写成","
for (初始化表达式1; 条件表达式2; 自增表达式3) {
// 循环体4
}
**执行顺序(记住)**:1243 --> 243 --> 243 --> 2......,直到条件表达式 返回 false 就停止循环。编写for循环代码,输出1-100之间的所有整数。
![](images/for循环执行流程图-代码.png)
  需求:
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变量输出即可。
![](images/正方形.png)
~~~
// 定义一个变量,用于存储 *
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来实现。
![
](images/三角形.png)
~~~
//定义一个变量,用于存储 *
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 分隔每个等式。
![](images/九九乘法表.png)
~~~
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)就是一个名字,用来对变量、函数、属性、参数进行命名,或者用做某些循环语句中的跳转位置的标记。
![](images/740839-20160601161025774-1227283954.png)
使用目的:使用变量可以方便地存储、获取、修改、删除内存中的数据。
*****
## 变量的命名规则和规范
**规则**:必须遵守的,不遵守会报错
1. 由字母、数字、下划线、$符号组成,不能以数字开头;
2. 不能是关键字和保留字,例如:var、if、for,enum
3. 区分大小写
![](images/JavaScript关键字和保留字.png)
**规范**:建议遵守的,不遵守不会报错
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);//
*/
```