目录
一、流程控制
1. 顺序结构、分支结构、循环结构
顺序结构:代码从上到下依次执行;
分支结构:if , if-else , if else-if , else-if , else{} , switch case ;
循环结构:for , while , do-while , forEach , for in for ;
var age = parseInt(prompt("请输入您的年龄"));
// prompt输出的是一个字符串,用parseInt转换
// console.log(typeof age);// string
if(age >= 18){
console.log("可以去看电影了---- 肖生克的救赎");
}else{
console.log("看什么看,回家敲代码去,敲10遍,你的问题都会迎刃而解了");
}
2. 三元运算符
var 变量 = 表达式1 ? 表达式2 : 表达式3;
执行原理: 首先判断表达式1为true还是flase,如果表达式1为true,则执行表达式2,并把结果返回给前面的变量;如果表达式1为false,则执行表达式3,并把结果返回给前面的变量。
3. 多分支语句
3.1 if else if else if… else{}
// 语法格式:
if(表达式1){
代码1;
}else if(表达式2){
代码2;
}else if(表达式3){
代码3;
}...
else{
代码5;
}
执行原理:
首先判断表达式1是否成立,如果表达式1为true,则执行代码1;后面的代码都不执行了;
如果表达式1为false,则继续判断表达式2,如果表达式2为true,则执行代码2;后面代码不再执行;
如果表达式2为false,则继续判断表达式3,如果表达式3为true,执行代码3,后面代码不再执行;
如果表达式3为false,则直接执行代码5;
例子: 成绩的结果
// * 如果是在90到100(包含)之间则 显示A级
// * 如果成绩是在80到90(包含)之间,则显示B级
// * 如果成绩是在70到80(包含)之间,则显示C级
// * 如果成绩是在60(包含)到70(包含)之间,则显示D级
// * 如果成绩在0到60(不包含)之间,则显示E级
var score = parseInt(prompt("请输入您的成绩"));
if (!isNaN(score)) {//表示的是数字
if (score > 90 && score <= 100) {//在90到100(包含)之间
console.log("A级");
} else if (score > 80) {//是在80到90(包含)之间
console.log("B级");
} else if (score > 70) {//是在70到80(包含)之间
console.log("C级");
} else if (score >= 60) {//是在60(包含)到70(包含)之间
console.log("D级");
} else {
console.log("E级");
}
} else {
console.log("您输入有误,请输入一个正确的数字");
}
3.2 switch-case
// 语法格式:
switch(表达式){
case "值1":
代码1;
break;
case "值2":
代码2;
break;
case "值3":
代码3;
break;
...
default:
代码6;
}
执行原理:
首先判断表达式的值,如果表达式的值和值1相同,则执行代码1,代码继续往下执行当遇到break,后面的代码就不在执行了;
如果表达式的值和值1不相同,则继续和值2进行比较,如果表达式的值和值2相同,则执行代码2,代码继续往下执行当遇到break,后面的代码就不在执行了;
…同理
如果表达式的值和上面的值都不相同,则执行default里面的代码
// 需求:用switch实现 获取一个人的成绩的级别,
//*如果是A级则显示90到100分之间
//* 如果是B级则显示80到90分之间
//* 如果是C级则显示70到80分之间
//* 如果是D级则显示60到70分之间
//* 否则显示0到59之间
var jiBie = "A";
switch(jiBie){
case "A":
console.log("90到100分之间");
break;
case "B":
console.log("80到90分之间");
break;
case "C":
console.log("70到80分之间");
break;
case "D":
console.log("60到70分之间");
break;
default:
console.log("0到59之间");
}
总结: 记得switch特点: 要给具体的值
如果给的是某个范围,推荐使用 if else if else if… else
如果给的是某个具体的值,推荐使用 switch-case
// 扩展:根据数字显示对应的星期几
var day = parseInt(prompt("请输入数字"));
switch(day){
case 1: console.log("星期一"); break;
case 2: console.log("星期二"); break;
case 3: console.log("星期三"); break;
case 4: console.log("星期四"); break;
case 5: console.log("星期五"); break;
case 6: console.log("星期六"); break;
case 7: console.log("星期天"); break;
default: console.log("您输入有误,请输入正确的数字");
}
3.3 循环
3.3.1 while循环
语法格式:
while(循环条件){
循环体;
结束条件;
}
//输出0-9
var i = 0 ;
while(i <= 9){
console.log(i) ;
i++;
}
3.3.2 do-while循环
语法格式:
do{
循环体;
}while(条件);
总结: do-while 至少执行一次循环体,while先判断条件,再决定是否执行循环体,有可能一次循环体也不执行;
3.3.3 for 循环
语法格式:
for(初始化表达式1;条件表达式2;自增表达式3){
循环体;
}
执行原理: 首先执行初始化表达式1,其次判断条件表达式2,若条件不成立,直接跳出整个循环;若条件成立,执行循环体,再执行自增表达式3,之后再判断条件是否成立,若不成立,则直接跳出整个循环,若成立继续循环,同理;
//1-100的平均值
var sum = 0;
for(var i = 1; i <= 100; i++){
sum += i;
}
console.log("1-100的平均值:" + (sum / 100));
3.3.4 break和continue关键字
break关键字: 当程序遇到break;直接跳出当前整个循环,此时这个循环结束,执行循环下面的代码。
while(true){
console.log("预览");//若没有break,则死循环
break;
}
console.log("跳出");//输出结果:预览 跳出
// 扩展:
for(var i = 0; i < 10; i++){
while(true){
console.log("break");
break;
}
}
//break跳出while循环,但依然在for循环中,即输出10个break
continue关键字: 当程序遇到continue,跳出当前本次循环,直接执行下一次循环。
var i=0;
while(i<5){
console.log(i);
continue;//遇到continue,跳出此次循环,i不执行自加,条件永远成立,出现死循环。
i++;
}
// 扩展:用continue求1-10的奇数和
var sum = 0;
var i = 1;
while(i <= 10){
if(i % 2 == 0){
i++;
continue;
}
sum += i;
i++;
}
console.log(sum);
二、数组
数组: 数组可存储多个数据
// 定义数组:
var arr = [1,2,3,4,5,6,7,8,9];
console.log(arr); // [1,2,3,4,5,6,7,8,9]
console.log(arr.length); // 9
// 定义空数组:
var arr= [];
console.log(arr.length);//空数组长度为0
注:
数组中的数据叫做元素,数组长度即为数组中元素的个数,数组下标从0开始,数组最大下标值为数组长度减1。
数组扩展案例:
1.去掉数组中重复的元素,其他元素存储到新数组中:
// 方法一:
// 思路: 准备一个新数组,将原数组中的元素一一放入新数组,
// 放入之前判断该元素是否存在新数组中,不存在的话就直接存入新数组。
var arr = [0, 1, 2, 0, 3, 0, 4, 0, 5, 6, 0, 7, 6, 8, 6, 9];
var newArr = [];//存放新元素
for (var i = 0; i < arr.length; i++) {
if (newArr.indexOf(arr[i]) == -1) {
newArr.push(arr[i]);
}
}
// newArr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
方法二:排序后相邻去除法
function uniqueArr(arr) {
arr.sort(); // [0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 6, 6, 7, 8, 9]
console.log(arr);
var newArr = [arr[0]];
console.log(newArr); // [0]
for (var i = 1; i < arr.length; i++) {
if (arr[i] != newArr[newArr.length - 1]) {
newArr.push(arr[i]);
}
}
console.log(newArr); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
return newArr;
}
var arr = [0, 1, 2, 0, 3, 0, 4, 0, 5, 6, 0, 7, 6, 8, 6, 9]
uniqueArr(arr)
// 方法三:
// 思路:获取没重复的最右一值放入新数组。
// 检测到有重复值时终止当前循环同时进入顶层循环的下一轮判断
function uniqueArr(arr){
var newArr = [];
for(var i=0; i<arr.length; i++){
for(var j=i+1; j<arr.length; j++){
if(arr[i] == arr[j]){
j = ++i;
}
}
newArr.push(arr[i])
}
console.log(newArr);
return newArr;
// [1, 2, 3, 4, 5, 0, 7, 8, 6, 9]
}
let arr = [0, 1, 2, 0, 3, 0, 4, 0, 5, 6, 0, 7, 6, 8, 6, 9]
uniqueArr(arr);
2.面试题:反转数组
核心思想图解:
var arr = [10,20,30,40,50,60,70];
// 循环的作用就是为了控制交换的次数
for(var i = 0; i < arr.lengtgh/2; i++){
var temp = arr[i];
arr[i] = arr[arr.length - 1 -i];
arr[arr.length - 1 -i] = temp;
}
consolw.log(arr);//输出:70,60,50,40,30,20,10
总结:
1.设置即循环次数为数组长度的一半;(交换次数为元素个数一半)
2.通过第三方变量交换首尾两个数据的值;
3.每一次循环尾部的值为 arr.length-1-i ;
三、函数
1. 函数基础
函数: 把一些相同的功能模块封装起来,放到函数里面,需要时可直接调用。
// 语法:
// 定义:
function 函数名(){
函数体;
}
调用:函数名();
步骤:
1.定义函数;
2.调用函数;
案例:
// 用函数求1-100的和
function everySum(){
var sum = 0;//存储和的
for(var i = 1; i <= 100; i++){
sum += i;
}
console.log("1-100之间的和:"+ sum);
}
// 记得调用函数
everySum();
函数参数:
// 计算两个数字的和:
function twoSum(x,y){//x,y为形参,即变量
var sum = x + y;
console.log(sum);
}
twoSum(10,20);//其中10和20为实参
总结:
形参:函数定义括号中的变量;
实参:函数调用时括号中的变量数值;
形参作用:接收实参的值。
2. 函数测试
2.1 数组冒泡排序
冒泡排序: 按照一定顺序进行排序(从小到大或从大到小)
两层循环: 第一层控制比较的轮数;第二层循环控制比较的次数。
有循环,有判断,有第三方变量;
5 4 3 2 1
第一轮比较: 4 3 2 1 5 比较次数:4次 arr.length - 1 - 0
第二轮比较: 3 2 1 4 5 比较次数:3次 arr.length - 1 - 1
第三轮比较: 2 1 3 4 5 比较次数:2次 arr.length - 1 - 2
第四轮比较: 1 2 3 4 5 比较次数:1次 arr.length - 1 - 3
总结:
比较轮数:arr.length - 1 (元素个数 - 1);
比较次数:arr.length - 1 - i ;
1.外层循环:0 ~ arr.length - 1;
2.内层循环:0 ~ arr.length - 1 - i;
3.判断内层循环的第一个值与第二个值的大小,通过第三方变量交换。
var arr = [5 , 4 , 3 , 2 , 1];
for(var i = 0; i < arr.length - 1; i++){
for(var j = 0; j < arr.length - 1 - i; j++){
//从小到大排序
if(arr[j] > arr[j + 1]){
var temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
console.log(arr);//输出:1,2,3,4,5
2.2 函数的返回值
函数返回值:一个完整的函数是有参数和返回值的。
工作中不会在函数里直接输出;一个函数是一个独立的功能模块;定义一个变量接收函数。
// 定义一个函数求和:
function getSum(x,y){
var sum = x + y;
return sum;
}
var result = getSum(10,20);
console.log(result + 10);
总结: 一个完整的函数,必须有参数和返回值;如果一个函数有返回值,则这个函数有return返回值,且调用这个函数时一定要定义一个变量来接收。
2.3 函数参数个数和返回值的问题
实参和形参个数不一致问题:
第一种情况:实参个数大于形参
function getSum(x,y){
return x + y;
}
var result = getSum(10,20,30,40,50,60);
console.log(result); // 30
结论: 若实参个数大于形参个数,那么多余的实参就会被丢弃。
第二种情况:实参个数小于形参
function getSum(x,y,z){//形参就是变量
return x + y + z;
}
var result = getSum(10,20);
console.log(result);//NaN (数字 + undefined = NaN 即 10 + 20 + z = NaN)
结论: 若实参个数小于形参个数,结果为 NaN 。
注意:若没有用到该多余的形参,可正确返回。即return x + y。
注:undefined 情况:
变量声明但没有赋值;
函数没有返回值,在调用时定义了变量来接收了,则函数默认返回值是undefined;
function getSum(x,y){
var sum = x + y;
}
var result = getSum(10,20);
console.log(result);//输出 undefined --->函数内部没有return
函数有返回值return,但后面没有内容,输出结果为undefined;
function getSum(x,y){
var sum = x + y;
return;
}
var result = getSum(10,20);
console.log(result);//输出 undefined
2.4 return后面的代码不执行
function getSum(x,y){
return x + y;
console.log("return后面的代码不执行!");//不执行
return x + y;//不执行
}
var result = getSum(10 , 20);
console.log(result);//输出:30
3. 函数自调用
(function(){
console.log("自调用函数");
})();
归纳: 该函数为匿名函数,没有函数名,操作DOM,做动画常用。
扩展: 斐波那契数列
案例:已知一对兔子每个月可以生一对小兔子,而一对兔子从出生后第三个月起每个月生一对小兔子,若一年内没有发生死亡,匿名一对兔子一年内能繁殖成多少对?
var num1 = 1;
var num2 = 1;
var sum = 0;
for(var i = 3; i <= 12; i++){
sum = num1 + num2;
num1 = num2;
num2 = sum;
}
console.log(sum);
sum i
1 1 2 3
1 2 3 4
2 3 5 5
3 5 8 6
5 8 13 7
8 13 21 8
13 21 34 9
21 34 55 10
34 55 89 11
55 89 144 12
4. arguments—伪数组
求n个数字的和: arguments;可以获取到用户传递的数据(工作经验:不知道用户会传递几个数据或几个实参)
arguments:可以随时拿到用户传递的参数,不用再写形参了。
之前用数组时要考虑实参与形参的个数的一致性,使用arguments可获取数组长度从而可以不考虑形参问题。
function fun(){
console.log(arguments.length); // 9
console.log(arguments); // 10,20,30,40,50,60,70,80,90
}
fun(10,20,30,40,50,60,70,80,90);
例: 伪数组arguments求任意数字的和
function getSum(){
var sum = 0;
for(var i = 0; i < arguments.length; i++){
sum += arguments[i];
}
return sum;
}
var result = getSum(10,20,30,40,50,60,70);
console.log(result);
总结: arguments 能让代码优化,不用考虑形参。
5. 命名函数和匿名函数
函数的两种写法:
1.命名函数-有函数名
function fun(){
console.log("命名函数");
}
fun();
2.匿名函数-无函数名:一般用在BOM和DOM
var f1 = function(){
console.log("匿名函数");
}
f1();
函数案例:封装一个函数,让用户传入年月日,判断这一天是这一年的第几天?
function getDays(year,month,day){
//先定义一个变量存储天数
var days = day;
//如果用户输入的是1月份,直接返回天数
if(month == 1){
return days;//遇到return,后面的代码不再执行
}
//若代码继续执行,则用户输入的不是1月份
//假设用户输入:2021-5-6;1月天数+2月+3月+4月+6天
//定义一个数组存储月的天数
var months = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
//用户输入的不是1月份,循环数组,把数组里的每个月天数加起来
for(var i = 0; i < month - 1; i++){
days += months[i];
}
if(isLeapYear(year) && month > 2){
days++;
}
return days;
}
var result = getDays(2000,3,1);
console.log(result);
function isLeapYear(year) {
return year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
}