[TOC] # **流程控制** &emsp;&emsp;流程控制语句是区分编程语言和非编程语言的标志。流程控制语句可以控制代码的执行流程或顺序,JavaScript中的流程控制结构有三种,分别是顺序结构,分支结构,循环结构。 <br> ## **顺序结构** &emsp;&emsp;从上到下执行的代码就是顺序结构,程序默认就是由上到下顺序执行的,如图: 顺序结构流程图 ![](images/顺序结构.png) <br> <br> ## **分支结构** 分支结构流程图 ![](images/分支结构.png) <br> ### **if 语句** &emsp;&emsp;if 语句作用:根据判断条件的结果(true或false),来决定执行哪一块代码。可分为以下三种结构。 <br> 1. **if 语句,如果 if 条件表达式成立,则执行分支体** **语法格式:** >[success] // 如果...那么... > if (/* 条件表达式 */) { > // 分支体 语句 > } &emsp;&emsp;需求:定义一个用于变量存储数值,判断这个变量是否是偶数 ``` var num = 8; if (num % 2 === 0) { console.log('偶数:' + num); } ``` <br> 2. **if else,如果 if 条件表达式不成立,则执行else分支体** >[success] //如果...那么... 否则... > if (/* 条件表达式 */){ > // if分支体 语句 > } else { > // else分支体 语句 > } &emsp;&emsp;需求:定义一个变量存储数值,判断这个变量是偶数还是奇数 ``` //能被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> &emsp;&emsp;需求:分数转换,把百分制转换成等级 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> ### **三元运算符** &emsp;&emsp;三元运算符是具有三个操作数的运算符,三元运算符又叫三目运算符,JavaScript中只有一种三元运算符。当if-else语句要返回一个结果时,可以使用三元运算符替换。 &emsp;&emsp;格式如下: >[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语句** &emsp;&emsp;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;] > } &emsp;&emsp;需求:定义一个变量存储星期,使用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> ### **布尔类型的隐式转换** &emsp;&emsp;流程控制语句会把括号中的表达式的值隐式转换(自动转换)成布尔类型,然后才使用转换后的结果作判断。除了流程控制语句的表达式,一元运算符 "!" 也会将值隐式转换成布尔类型。 ``` //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> ## **循环结构** &emsp;&emsp;在JavaScript中,循环是指重复地做一件事情,JavaScript中的循环语句有三种,while循环语句、do-while循环语句和for循环语句。 ![](images/循环结构.png) <br> ### **while语句** &emsp;&emsp;while语句执行流程图 ![](images/while语句执行流程图.png) &emsp;&emsp;语法格式: >[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语句** &ensp;&ensp;do-while循环和while循环非常像,二者经常可以相互替代,但是do-while的特点是不管条件成不成立,do循环体都会先执行一次。 do-while执行流程图 ![](images/dowhile执行流程图.png) &ensp;&ensp;语法格式: ``` do { // 循环体; } while (循环条件); ``` &ensp;&ensp;需求: 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语句** &ensp;&ensp;JavaScript的循环结构中,除了while和do-while循环,还有for循环。**while和do-while一般用于循环次数不确定的情况,for循环一般用于循环次数确定的情况。** <br> &ensp;&ensp;for循环执行流程图 ![](images/for循环执行流程图.png) &ensp;&ensp;语法格式: >[success]// for循环括号中表达式之间是用";"号分隔的,千万不要写成"," for (初始化表达式1; 条件表达式2; 自增表达式3) { // 循环体4 } **执行顺序(记住)**:1243 --> 243 --> 243 --> 2......,直到条件表达式 返回 false 就停止循环。编写for循环代码,输出1-100之间的所有整数。 ![](images/for循环执行流程图-代码.png) &ensp;&ensp;需求: 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循环** &ensp;&ensp;在之前学习的for循环中,我们解决问题是:重复执行某一个操作。如果一个重复的操作需要做N次,此时得使用嵌套循环。 &ensp;&ensp;语法格式: >[success]for (初始化表达式1; 条件表达式2; 自增表达式3) { // 循环体 for (初始化表达式1; 条件表达式2; 自增表达式3) { // 循环体 } } &ensp;&ensp;需求: 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** &ensp;&ensp;break:立即跳出当前整个循环(注意:如果是多层循环,则跳出当前层循环),即循环结束,开始执行循环后面的代码(直接跳到大括号) &ensp;&ensp;continue:立即跳出当前(本次)循环,继续下一次循环(跳到i++的地方) &ensp;&ensp;需求: 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变量 ## 什么是变量 &emsp;&emsp;变量是计算机内存中存储数据的标识符,根据变量名称可以获取到内存中存储的数据。 &emsp;&emsp;在日常生活中,有些东西是固定不变的,有些东西则会发生变化。例如,人的姓名和生日是固定不变的,但心情和年龄却会随着时间变化而变化。人们把那些会发生变化的东西称为变量。 &emsp;&emsp;当程序需要将值保存起来以备将来使用时,便将其赋值给一个变量。变量(variable)是一个用于保存值的占位符,可以通过变量名称来获得对值的引用。 标识符(Identifier)就是一个名字,用来对变量、函数、属性、参数进行命名,或者用做某些循环语句中的跳转位置的标记。 ![](images/740839-20160601161025774-1227283954.png) 使用目的:使用变量可以方便地存储、获取、修改、删除内存中的数据。 ***** ## 变量的命名规则和规范 **规则**:必须遵守的,不遵守会报错 1. 由字母、数字、下划线、$符号组成,不能以数字开头; 2. 不能是关键字和保留字,例如:var、if、for,enum 3. 区分大小写 ![](images/JavaScript关键字和保留字.png) **规范**:建议遵守的,不遵守不会报错 1. 变量名具有意义。可顾名思义,例如age、name; 2. 遵守匈牙利命名法、驼峰命名法和帕斯卡命名法。 驼峰命名法:第一个单词首字母小写,后面单词的首字母需要大写。例如:userName、userPassword; ### 匈牙利命名法 &emsp;&emsp;引用于[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)匈牙利命名法是电脑程序设计中的一种变量命名规则,此命名法又可细分为:系统匈牙利命名法和匈牙利应用命名法。 &emsp;&emsp;匈牙利命名法具备语言独立的特性,并且首次在BCPL语言中被大量使用。由于BCPL只有机器字这一种数据类型,因此这种语言本身无法帮助程序员来记住变量的类型。匈牙利命名法通过明确每个变量的数据类型来解决这个问题。 &emsp;&emsp;在匈牙利命名法中,一个变量名由一个或多个小写字母开始,这些字母有助于记忆变量的类型和用途,紧跟着的就是程序员选择的任何名称。这个后半部分的首字母可以大写,以区别前面的类型指示字母。 匈牙利命名法: >[success]变量名=数据类型+对象描述 * **数据类型**:指点是JavaScript中六种数据类型之一,`undefined`、`null`、`boolean`、`number`、`string`和`Object` * **对象描述**:指对象名字全称或名字的一部分,而且要有明确含义,易记而且还要好理解 &emsp;&emsp;有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字符串 ~~~ &emsp;&emsp;如上面的示例中的变量名称`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> ### 驼峰命名法 &emsp;&emsp;当变量名和函数名称是由二个或多个单字链接在一起,而构成的唯一识别字时,利用“驼峰式大小写”来表示,可以增加变量和函数的可读性。 &emsp;&emsp;“驼峰式大小写(Camel-Case)一词来自Perl语言中普遍使用的大小写混合格式,而Larry Wall等人所著的畅销书《Programming Perl》(O'Reilly出版)的封面图片正是一匹骆驼。” &emsp;&emsp;“驼峰式大小写”命名规则可视为一种惯例,并无绝对与强制,为的是增加识别和可读性。一旦选用或设置好命名规则,在程序编写时应保持一致格式。 驼峰命名法常见有两种格式: * **小驼峰式命名法(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> ### 帕斯卡命名法 &emsp;&emsp;Pascal命名法(Pascal Case,巴斯卡命名法/帕斯卡命名法),电脑程序编写时的一套命名规则(惯例)。 &emsp;&emsp;当变量名和函数名称是由二个或二个以上单字链接在一起,而构成的唯一识别字时,用以增加变量和函数的可读性。 &emsp;&emsp;单字之间不以空格断开或连接号(`-`)、下划线(`_`)链接,第一个单前缀字母采用大写字母;后续单字的首字母亦用大写字母,例如:`FirstName`、`LastName`。每一个单字的首字母都采用大写字母的命名格式,被称为“Pascal命名法”,源自于Pascal语言的命名惯例,也有人称之为“大驼峰式命名法”(Upper Camel Case),为驼峰式大小写的子集。 &emsp;&emsp;“Pascal命名法”可视为一种命名惯例,并无绝对与强制,为的是增加识别和可读性。一旦选用或设置好命名规则,在程序编写时应保持格式的一致性。 &emsp;&emsp;有关于帕斯卡命名法更详细的介绍可以[点击这里](https://zh.wikipedia.org/wiki/%E5%B8%95%E6%96%AF%E5%8D%A1%E5%91%BD%E5%90%8D%E6%B3%95)阅读。 &emsp;&emsp;虽然上面三种方法在JavaScript中命名变量常见的方法,也是很多规范推荐使用的命名方法;但除此之外还有别的方法。比如说变量名有两个或多个单词时,可以在多个单词间使用`-`或`_`连接起来。如`first-name`或者说`first_name`。 ***** <br> ## 变量的使用 &emsp;&emsp;在使用变量之前,首先要把变量定义出来,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);// */ ```