7.JavaScript基础-流程控制-if
7.1、JavaScript流程控制基本概念
- 默认情况下,浏览器会按书写从上至下顺序执行程序中的每一行代码,但是这并不能满足我们所有的开发需求;
- 为了方便我们控制程序的运行流程,JavaScript提供3种流程结构,不同的流程结构可以实现不同的运行流程。这3种流程结构分别是顺序、选择、循环三种基本控制结构构造。
1、顺序结构:默认的流程结构,按照书写顺序从上至下执行每一条语句
2、选择结构:对给定的条件进行判断,再根据判断结果来决定执行哪一段代码
switch、if
3、循环结构:在给定条件成立的情况下,反复执行某一段代码
while、do-while、for
7.2、JavaScript - 选择结构 if
1. if 第一种形式
if(条件表达式){
条件满足执行的语句;
}
2. if 第一种形式的特点
当条件表达式为真的时候,就会执行{}中所有的代码,并且只会执行一次
3. if 第二种形式
if(条件表达式){
条件成立执行的语句;
}else{
条件不成立执行的语句;
}
4. if 第二种形式的特点
当条件满足就执行if后面{}中的代码
当条件不满足就执行else后面{}中的代码
并且两个{}只有一个会被执行,并且只会被执行一次
5. if 第三种形式
if(条件表达式A){
条件A满足执行的语句;
}else if(条件表达式B){
条件B满足执行的语句;
}
......
else{
前面所有条件都不成立时执行的语句;
}
6. if 第三种形式的特点
会从上至下的依次判断每一个条件表达式,哪一个条件表达式满足,就执行哪一个条件表达式后面{}中的代码
如果前面所有的条件表达式都不满足,就会执行else后面{}中的代码
并且众多的大括号只有一个会被执行,并且只会执行一次。
7、if的注意点
7.1.对于非布尔类型的数据,会先转换成布尔类型再判断
if (null){//转为bool类型,false
console.log("语句A");
}
console.log("语句B");
7.2、对于==、===判断,将常量写在前面
常量写前面是担心将== 写为 = 变为了赋值语句,产生错误。将常量写在前面,控制台会帮忙报错。
let num = 10;
// if (num = 5){
if (5 = num){
console.log("语句A");
}
console.log("语句B");//Uncaught ReferenceError: Invalid left-hand side in assignment
7.3、if、else if、else后面的大括号都可以省略,但是省略之后只有紧随其后的语句受到控制
if (false)
console.log("statement A");//只有这条语句受到if语句的控制。不被输出
console.log("statement B");//被输出
7.4、在JavaScript中分号(;)也是一条语句(空语句)
if (false);{
console.log("statement A");//被输出
console.log("statement B");//被输出
}
7.5、if选择结构可以嵌套使用
7.6、当if选择结构省略大括号时,else if、else会自动和距离最近没有被使用的if匹配。
if (0)
if (1)
console.log("A");
else
console.log("B");
else
if (1)
console.log("C");//被输出
else
console.log("D");
8.练习
8.1、需求:接受用户输入的整数,判断是否是偶数:偶数输出YES,奇数输出NO
在企业开发中,如果条件满足之后只有一句代码需要执行,那么就用三目运算符
在企业开发中,如果条件满足之后只有多句代码需要执行,那么就用选择结构。
因为三目运算符中执行语句只能是一句话,不能是多句话。
/*方法一*/
let num = prompt("请输入数字");
if (num % 2 == 0 ){
alert("你喜欢偶数啊");
} else{
alert("喜欢奇数,噗");
}
/*方法二*/
num % 2 == 0 ? alert("你喜欢偶数啊") : alert("喜欢奇数,噗")
8.2、需求:有3个变量a、b、c,要求至少使用两种方法将升序排序后输出
排序前:a = 5; b = 3; c = 4;
排序后:a = 3; b = 5; c = 5;
方法一:
let a = 5; b = 3; c = 4;
console.log(a, b, c);
//1.利用a、b比较,如果a>b,就交换a和b中保存的数据
if (a > b){
temp = a;
a = b;
b = temp;
}
//2.利用a、c比较,如果a>c,就交换a和c中保存的数据
if (a > c){
temp = a;
a = c;
c = temp;
}
//3.利用c、b比较,如果b>c,就交换b和c中保存的数据
if (b > c){
temp = b;
b = c;
c = temp;
}
console.log(a, b, c);
方法二:
let a2 = 10; b2 = 3; c2 = 12;
console.log(a2, b2, c2);
//1.利用a2、b2比较,如果a2>b2,就交换a2和b2中保存的数据
if (a2 > b2){
temp = a2;
a2 = b2;
b2 = temp;
}
//2.利用c2、b2比较,如果b2>c2,就交换b2和c2中保存的数据
if (b2 > c2){
temp = b2;
b2 = c2;
c2 = temp;
}
//2.利用a2、b2比较,如果a2>b2,就交换a2和b2中保存的数据
if (a2 > b2){
temp = a2;
a2 = b2;
b2 = temp;
}
console.log(a2, b2, c2);
7.3、JavaScript-选择结构 switch
1.switch格式:
switch(表达式){
case 表达式A:
语句A;
break;
case 表达式B:
语句B;
break;
... ...
default:
前面所有case都不匹配执行的代码;
break
}
2.switch特点
2.1、会从上至下的依次判断每一个case是否和()中表达式的结果相等(数据和数据类型都相等===),如果相等就执行对应case后面的代码,如果前面所有case都不匹配,那么就会执行default后面的代码。
2.2、并且所有的case和default只有一个会被执行,并且只会被执行一次
2.3、case后可以是常量也可以是变量
let day = 7;
switch (day) {
case 1:
console.log("Monday");
break;
case 2:
console.log("tuesday");
break;
case 3:
console.log("Wednesday");
break;
default:
console.log("再見");
break;
}
3.注意点:
3.1. case判断的是===,而不是==
let num = 123;
switch (num) {
case "123":
console.log("字符串123");
break;
case 123:
console.log("数字123");
break;
default:
console.log("Other");
break;
}
3.2. ()中可以是常量也可以是变量还可以是表达式
let num2 = 123;
// switch (num2) {//变量
// switch (123) {//常量
switch (122 + 1) {//表达式
case "123":
console.log("字符串123");
break;
case 123:
console.log("数字123");
break;
default:
console.log("Other");
break;
}
3. 3. case后面可以是常量也可以是变量还可以是表达式
let num3 = 123;
switch (123) {//表达式
// case 123://常量
// case num3://变量
case 100 + 23://表达式
console.log("数字123");
break;
default:
console.log("Other");
break;
}
3.4. break的作用是立即结束整个switch语句
在switch语句中一旦case或者default被匹配,那么其他的case和default都会失效
let num4 = 1;
switch (num4) {
case 1:
console.log("1");
// break;
case 2:
console.log("2");
// break;
default:
console.log("Other");
break;
}//打印1 2 Other
3.5. default不一定要写在最后。switch中的default无论放到什么位置,都会等到所有case都不匹配再执行
let num5 = 7;
switch (num5) {
default:
console.log("Other");
break;
case 1:
console.log("1");
break;
case 2:
console.log("2");
break;
}//打印Other
3.6. 和if、else中的else一样,default也可以省略
let num6 = 7;
switch (num6) {
case 1:
console.log("1");
break;
case 2:
console.log("2");
break;
}//没有输出结果而已
4.if-switch如何选择
在企业开发中如果是对区间进行判断,那么建议使用if
在企业开发中如果是对几个固定的值的判断,那么建议使用switch
原则:能用if就用if
7.4、JavaScript-while循环
1.if的格式、特点:
if (条件表达式){
条件满足执行的语句;
}
if的特点:只有条件表达式为真才会执行后面{}中的代码
大括号中的代码只会被执行一次
2.while的格式
while (条件表达式){
条件满足执行的语句;
}
while的特点:只有条件表达式为真才会执行后面{}中的代码
大括号中的代码有可能会被执行多次
3.while的执行流程
3.1、首先会判断条件表达式是否为真,如果为真就执行后面{}中的代码
3.2、执行完后面{}中的代码,会再次判断条件表达式是否为真
3.3、如果条件表达式还为真,那么会再次执行后面{}中的代码
3.4、重复3.1-3.3直到条件表达式不为真
4.书写循环结构的规则
4.1、不管三七二十一,先写上循环结构的代码
4.2、将需要重复执行的代码拷贝到{}中
4.3、在()中指定循环结束条件
5.注意点
5.1.什么是死循环?
条件表达式永远为真的循环结构,称之为死循环
while(true){
console.log("123");
}
5.2.什么是循环体?
循环结构后面的{}我们称之为循环体。
5.3.和if一样对于非Boolean类型的值,会先转换成Boolean类型再判断
while(null){//null转换为Boolean类型后为false
console.log("第3小点对应代码片段");//不执行
}
5.4.和if一样while后如果只有一条语句,可以省略大括号。
while(false)
console.log("第4小点对应代码片段1");//不输出
console.log("第4小点对应代码片段2");//输出
如果省略了后面的大括号,那么只有紧随其后的一条语句受到控制
5.5.和if一样,不能在()后面写分号(; )
while(false);
{
console.log("第5小点对应代码片段1");//输出
console.log("第5小点对应代码片段2");//输出
}
5.6.最简单死循环写法:while(1);
6.练习
6.1、练习1:打印1-100之间 7的倍数,并统计个数
let num = 1;
let count = 0;
while(num <= 100){
if (num % 7 === 0) {
console.log(num);
count ++;
}
num ++;
}
console.log(count);
7.5、JavaScript-do-while循环
1.while的格式
while(条件表达式){
需要重复执行的代码;
}
while循环的特点:只有条件表达式为真,才会执行循环体。
2.do-while的格式
do{
需要重复执行的代码;
}while (条件表达式);
do-while循环的特点:只无论条件表达式是否为真,循环体都会被执行一次。
3.do-while循环和while的选择
3.1.在企业开发中大部分情况下,do-while循环和while是可以互换的
3.2.在企业开发中如果循环体中的代码无论如何都要先执行一次,那么建议使用do-while循环
3.3.在企业开发中其他的情况都建议使用while循环
案例:要求用户输入密码,判断输入密码是否正确(假设正确密码是123456)
如果正确,输入“欢迎回来”
如果不正确,要求用户重新输入
方法一:while
let password = prompt("请输入密码");
while (password !== "123456"){
password = prompt("请输入密码");
}
alert("欢迎回来");
方法二:dowhile
let password = 1;//若定义在{}之中,会成为局部变量,{}后的部分无法使用该变量
do {
password = prompt("请输入密码");
}while (password !== "123456");
alert("欢迎回来");
7.6、JavaScript变量作用域
1.在JavaScript中定义变量有两种方式
ES6之前:var 变量名称;
ES6开始:let 变量名称;
2.两种定义变量方式的区别
如果通过var定义变量,可以重复定义同名的变量,并且不会报错,并且后定义的会覆盖先定义的
var num = 123;
var num = 124;
console.log(num);//124
如果通过var定义变量,可以先使用后定义(预解析)
console.log(value);//undefined
var value = 123;
如果通过let定义变量,不可以重复定义同名的变量
如果通过let定义变量,不可以先使用后定义,因为浏览器不会对let定义的变量进行预解析
无论是通过let还是通过var定义的全局变量都是从定义的那一行到文件末尾都可以使用
如果是通过var定义的局部变量,和全局变量后续都可以被使用
如果是通过let定义的局部变量,那么这个变量只能在当前定义变量的{}中使用
3.什么是全局变量
全局变量就是定义在{}外面的变量
4.什么是局部变量
局部变量就是定义在{}里面的变量
5.全局变量和局部变量的区别
如果是全局变量,那么有效范围是从定义变量的那一行开始直到文件的末尾都可以使用
如果是局部变量,那么有效范围是从定义变量的那一行开始直到大括号结束位置
7.7、JavaScript-for循环
1.for循环的格式
1 2/5/8 4/7
for(初始化表达式; 条件表达式, 循环后增量表达式){
3/6
需要重复执行的代码
}
2.for循环的特点
for循环的特点和while循环的特点一样,只有条件表达式为真,才会执行循环体
3.for循环的执行流程
3.1、首先会执行初始化表达式,并且只会执行一次
3.2、判断条件表达式是否为真,如果条件表达式为真,就执行循环体
3.3、执行完循环体就会执行循环后增量表达式
3.4、重复3.2-3.3,直到条件表达式不为真为止
4.for循环同while循环对比
//1.初始化表达式
let num = 1;
//2.条件表达式
while (num <=10 ){
console.log("发射子弹" + num);
//3.循环后增量表达式
num++;
}
//1.初始化表达式
// let numF = 1;
//2.条件表达式
for (let numF = 1;numF <=10;numF++){
console.log("发射子弹" + numF);
//3.循环后增量表达式
// numF++;
}
5.for循环同while循环如何选择
在企业开发中,由于for循环比while灵活,所以能用for循环就用for循环
//1.初始化表达式
let num = 1;
//2.条件表达式
while (num <=10 ){
console.log("发射子弹" + num);
//3.循环后增量表达式
num++;
}
//如果是while循环,在循环结束后还可以使用用于控制循环结束的变量
console.log(num);//11
//1.初始化表达式
// let numF = 1;
//2.条件表达式
for (let numF = 1;numF <=10;numF++){
console.log("发射子弹" + numF);
//3.循环后增量表达式
// numF++;
}
//如果是for循环,在循环结束之后可以让外加使用,也可以不让外界使用
//let numF = 1;写在for的()内部,外界无法使用,写在for的上面,可以让外界使用
console.log(numF);//Uncaught ReferenceError: numF is not defined
6.for循环注意点
1.在for循环中“初始化表达式”,“条件表达式”、“循环后增量表达式”都可以不写
while(){//while循环不能省略条件表达式
console.log("123");
}
for(;;){//for循环可以省略条件表达式,默认就是真。如果不写就相当于while(1);
console.log("123");
}
2.其他注意点和while一样
7.8、JavaScript-break关键字
1.什么是break关键字
break关键字可以用于switch语句和循环结构中
在switch语句中break关键字的作用是立即结束当前的switch语句
在循环结构中break关键字的作用也是立即结束当前的循环
let num0 = 1;
while (num0 <= 10){
console.log("发射子弹" + num0);
num0++;
break; //只输出一次发射子弹
console.log("lalala");//不打印
}
2.break注意点:
2.1、break关键字后面不能编写任何的语句,因为永远执行不到。
2.2、如果在循环嵌套的结构中,break结束的是当前所在的循环结构。
for(let i = 0; i < 5; i++){
console.log("外面的循环结构" + i);//答应五次
for(let j = 0; j < 5; j++){
console.log("里面的循环结构----" + j);
break;
}
}
7.9、JavaScript-continue关键字
1.什么是continue关键字?
continue关键字只能用于循环结构
在循环结构中continue关键字的作用是跳过本次循环,进入下一次循环
for (let num = 1; num <= 10 ;num ++){
if (num === 1 ){
continue;
console.log("后面的代码永远不执行");
}
console.log("发射子弹" + num);//没有“发射子弹1”了
}
2.continue关键字注意点
2.1、continue关键字后面和break一样,不能编写其它的代码,因为执行不到
2.2、和break一样,如果continue关键字出现在循环结构中,只会跳过当前所在的循环。
for(let i = 0; i < 5; i++){
console.log("外面的循环结构" + i);//答应五次
for(let j = 0; j < 5; j++){
if (j === 1 ){
continue;
console.log("后面的代码永远不执行");
}
console.log("里面的循环结构----" + j);
}
}
7.10、JavaScript-循环嵌套规律
1.、循环嵌套规律:
外循环控制的是行数,内循环控制的是列数
2.练习1
需求:在界面中输出如下图形
*****
****
***
***
*
//规律:如果尖尖朝下,那么只需要修改内循环的初始化表达式为外循环初始化表达式的变量即可
for (let i = 0; i <5; i++){
for (let j = i; j < 5; j++){
document.write("*");
}
document.write("<br>")
}
3.练习2
需求:在界面中输出如下图形
*
**
***
****
*****
//规律:如果尖尖朝上,那么只需要修改内循环的条件表达式为外循环初始化表达式的变量即可
for (let i = 0; i <5; i++){
for (let j = 0 ; j <= i; j++){
document.write("*");
}
document.write("<br>")
}
8.JavaScript基础-数组
8.1、JavaScript-数组基本概念
0.需求:要求定义变量保存一个人的姓名
let name1 = "lnj";
需求:要求定义变量保存一班级所有人的姓名
` let name1 = "lnj";
let name2 = "lnj12";
let name3 = "ln12";
子子孙孙无穷尽也,写起来太费劲。因此出现了数组`
1.什么是数组?
数组就是专门用于存储一组数据的
注意点:和我们前面学习的Number/String/Boolean/Null/Undefined不同(这些事基本数据类型),
而我们今天学习的数组(Array)不是基本数据类型,是引用数据类型(对象类型)
2.如何创建一个数组?
let 变量名 = new Array(size);
size:尺寸大小,用于表明要存储多少个数据。
3.如何操作数据
3.1、如何往数组中存储数据
变量名称[索引号] = 需要存储的数据;
let str = new Array(3);
console.log(str);
str[0] = "不高兴";
console.log(str);
3.2、如何从数组中获取存储的数据
变量名称[索引号];
console.log(str[0]);
4.数组注意点
4.1.和其他编程语言不同,如果数组对应的索引中没有存储数据,默认存储的就是undefined。
其他编程语言中默认保存的是垃圾数据或者0
let str = new Array(3);
console.log(str[0]);//undefined
console.log(str[1]);//undefined
console.log(str[2]);//undefined
4.2.和其他编程语言不同,JavaScript中访问了数组中不存在的索引不会报错,会返回undefined
其他编程语言一旦超出索引范围就会报错或者返回脏数据
let str = new Array(3);
console.log(str[666]);//undefined
4.3.和其他编程语言不同,当JavaScript中数组的存储空间不够时,数组会自动扩容
其他编程语言种数组的大小是固定的
let str = new Array(3);
str[0] = "yt";
str[1] = "asd";
str[2] = "qe";
str[3] = "rfg";
console.log(str);//["yt", "asd", "qe", "rfg"]
4.4.和其他编程语言不同,JavaScript的数组可以存储不同类型数据
在其他编程语言中数组只能存储相同类型的数据
let str = new Array(3);
str[0] = 123;
str[1] = "asd";
str[2] = true;
str[3] = null;
console.log(str);//(4) [123, "asd", true, null]
4.5.和其他编程语言不同,JavaScript中数组分配存储空间不一定是连续的
其他语言数组分配的存储空间都是连续的,JavaScript数组是采用“哈希映射”的方式分配存储空间
什么是哈希映射?好比字典可以通过偏旁部首找到对应的汉字,我们可以通过索引找到对应空间
在浏览器中各大浏览器也对数组分配存储空间进行了优化
如果存储的都是相同类型的数据,那么就会尽量分配连续的存储空间
如果存储的都是不相同类型的数据,那么就不会分配连续的存储空间
4.6.创建数组的其他方式
1、通过构造函数创建数组
let 变量名称 = new Array(size);创建指定大小的数组
let 变量名称 = new Array();创建空数组
let 变量名称 = new Array(data1, data2, ....);创建带数据的数组
2、通过字面量创建数组(因为比较简单,因此企业中常用)
let 变量名称 = [];创建一个空数组。等同于 let 变量名称 = new Array();创建空数组
let 变量名称 = [data1, data2, ....];创建带数据的数组。等同于 let 变量名称 = new Array(data1, data2, ....);创建带数据的数组
8.2、JavaScript-数组遍历
1.什么是数组的遍历
数组的遍历就是依次取出数组中存储的所有数据,就称之为数组的遍历
for (let i = 0; i < arr.length; i++){
console.log(arr[i]);
}
8.3、JavaScript-数组解构赋值-ES6
1.什么是数组解构赋值
解构赋值是ES6新增的一种赋值方式
let arr = ["1", "2", "3"];
let a = arr[0];//取数组的某个值赋值给变量
let b = arr[1];
let c = arr[2];
console.log("a=" + a);//1
console.log("b=" + b);//2
console.log("c=" + c);//3
//上面的赋值方法比较复杂,因此ES6新增了赋值方法:解构赋值
let [d, e, f] = arr;
console.log("d=" + d);//1
console.log("e=" + e);//2
console.log("f=" + f);//3
2.数组解构赋值的注意点
2.1、在数组解构赋值中,等号左边的格式必须和等号右边的格式一模一样,才能完全解构(完全解构:数组中的每个值都取出来)
let [d, e, f] = [1, 2, 3];
let [d, e, f] = [1, 2, [2, 5]];
let [d, e, [f, g]] = [1, 2, [2, 5]];
console.log("d=" + d);//1
console.log("e=" + e);//2
console.log("f=" + f);//2, 5
console.log("g=" + g);//2, 5
2.2、在数组的解构赋值中,左边的个数可以和右边的个数不一样
let [d, e] = [1, 2, 3];
console.log("d=" + d);//1
console.log("e=" + e);//2
2.3、在数组的解构赋值中,右边的个数可以和左边的个数不一样
let [d, e, f] = [1];
console.log("d=" + d);//1
console.log("e=" + e);//undefined
console.log("f=" + f);//undefined
2.4、在数组的解构赋值中,如果右边的个数和左边的个数不一样,那么我们可以给左边指定默认值
let [d, e = 666, f = 999] = [1];
console.log("d=" + d);//1
console.log("e=" + e);//666
console.log("f=" + f);//999
2.5、在数组的解构赋值中,如果右边的个数和左边的个数不一样,那么如果设置默认值会被覆盖
let [d, e = 666] = [1, 5 ,6];
console.log("d=" + d);//1
console.log("e=" + e);//5
2.6、在数组的解构赋值中,还可以使用ES6中新增的扩展运算符来打包剩余的数据
ES6新增的扩展运算符:...
let [d, ...e] = [1, 3, 5];
console.log("d=" + d);//1
console.log("e=" + e);//3,5
2.7、在数组的解构赋值中,如果使用了扩展运算符,那么扩展运算符只能写在最后
let [...d, e] = [1, 3, 5];
console.log("d=" + d);//Rest element must be last element
console.log("e=" + e);
8.4、JavaScript-数组增删改查
需求:获取数组中索引为1的那个数据(查)
console.log(arr[1]);//b
需求:将索引为1的数据修改为m(改)
arr[1] = "m";
console.log(arr[1]);//m
需求:将索引为1的数据修改为d,索引为2的修改为e(改)
方法一:
arr[1] = "d";
arr[2] = "e";
console.log(arr);//"a", "d", "e"
方法二:
splice参数1:从什么位置开始
splice参数2:需要替换多少个元素
splice参数3:新的内容
arr.splice(1, 2, "d", "e");
console.log(arr);//"a", "d", "e"
需求:在数组最后添加一条数据(增)
方法一:
arr[3] = "d";
console.log(arr);//["a", "b", "c", "d"]
方法二:
push可以在数组的最后新增一条数据,并且会将新增内容之后数组当前的长度返回给我们
let res = arr.push("d");//push有返回值,返回数组长度
console.log(res);//4,数组长度
console.log(arr);//["a", "b", "c", "d"]
需求:在数组最后添加两条数据(增)
方法一:
arr.push("d");
arr.push("e");
console.log(arr);//["a", "b", "c", "d", "e"]
方法二:
数组的push方法可以接收一个或多个参数
arr.push("d","e");
console.log(arr);//["a", "b", "c", "d", "e"]
需求:在数组最前面添加一条数据(增)
unshift方法和push方法一样,会将新增内容之后当前数组的长度返回给我们。
let res = arr.unshift("m");
console.log(res);//4
console.log(arr);// ["m", "a", "b", "c"]
需求:在数组最前面添加两条数据(增)
方法一:
arr.unshift("m");
arr.unshift("w");
console.log(arr);// ["w", "m", "a", "b", "c"]
方法二:
unshift方法和push方法一样,可以接受一个或多个参数
arr.unshift("m", "w");
console.log(arr);//["w", "m", "a", "b", "c"]
需求:要求删除数组最后面一条数据(删)
数组的pop方法可以删除数组中的最后一条数据,并且将删除的数据返回给我们
let res = arr.pop();
console.log(res);//c
console.log(arr);//["a", "b"]
需求:要求删除数组最前面一条数据(删)
数组的pop方法可以删除数组中的最前面一条数据,并且将删除的数据返回给我们
let res = arr.shift();
console.log(res);//a
console.log(arr);//["b", "c"]
需求:要求删除数组中索引为1的数据(删)
arr.splice(1, 1);从索引为1的元素开始,删除一条数据
splice参数一:从什么位置开始
splice参数二:需要删除多少个元素
arr.splice(1, 1);
console.log(arr);//["a", "c"]
需求:要求删除数组中除0以外的所有数据(删)
arr.splice(1,2);
console.log(arr);//["a"]
8.5、JavaScript-数组常用方法
1.如何清空数组(企业中常用的三个方式)
方法一:
arr = [];
console.log(arr);
方法二:
arr.length = 0;
console.log(arr);//[]
方法三:
arr.splice(0, arr.length);
console.log(arr);//[]
2.如何将数组转换为字符串
let str = arr.toString();
console.log(str, typeof str);//1,2,3,4,5,6 string
3.如何将数组转换成指定格式字符串
join方法默认情况下如果没有传递参数就是调用toString()方法
join方法如果传递了参数,就会将传递的参数作为元素和元素的链接符号
let str = arr.join("+");
console.log(str, typeof str);//1+2+3+4+5+6 string
4.如何将两个数组拼接为一个数组
方法一:不行
let arr1 = [2, 6, 8];
let arr2 = [1, 5, 7];
//数组不能使用 + 加号进行拼接,如果使用加号进行拼接会先转换成字符串再拼接。如下:
let res = arr1 +arr2;
console.log(res, typeof res);//2,6,81,5,7 string
方法二:
let arr1 = [2, 6, 8];
let arr2 = [1, 5, 7];
concat不会修改原有的数组,会生成一个新的数组返回给我们
let res = arr1.concat(arr2);
console.log(res, typeof res);//[2, 6, 8, 1, 5, 7] "object"
方法三:(企业开发中推荐使用)
let arr1 = [2, 6, 8];
let arr2 = [1, 5, 7];
//concat不会修改原有的数组,会生成一个新的数组返回给我们
扩展运算符在解构赋值中(等号的左边)表示将剩余的数据打包成一个新的数组
扩展运算符在等号的右边,表示将数组中所有的数据解开,放到所在的位置。
let res = [...arr1, ...arr2];//...扩展运算符
console.log(res, typeof res);//[2, 6, 8, 1, 5, 7] "object"
5.如何对数组中的内容进行反转
[1, 2]变[2, 1]
reverse()会修改原有的数组
let res = arr.reverse();
console.log("原始值=1,2,3,4,5,6", "反转后="+res, "反转后原始值变为 = "+arr);//原始值=1,2,3,4,5,6 反转后=6,5,4,3,2,1 反转后原始值变为 = 6,5,4,3,2,1
6.如何截取数组中指定范围内容
slice()方法是包头不包尾(包含起始位置,不包含结束的位置)
let res = arr.slice(1, 3);//包含开始位置,不包含结尾
console.log(res);//[2, 3]
7.如何查找元素在数组中的位置
indexOf()方法如果找到了指定的元素,就会返回元素对应的位置
indexOf()方法如果没有找到指定的元素,就会返回-1
注意点:
indexOf()方法默认是从左至右查找,一旦找到就会立即停止查找。
console.log(arr.indexOf(3));//2
console.log(arr.indexOf(9));//-1
参数一:需要查找的元素
参数二:从什么位置开始查找
console.log(arr.indexOf(3, 2));
lastIndexOf()方法默认是从右至左查找,一旦找到就会立即停止查找。同indexOf也可以接受两个参数
console.log(arr.lastIndexOf(3));
8.如何判断数组中是否包含某个元素
方法一:
可以通过indexOf和lastIndexOf的结果,判断是否是-1即可
方法二:
console.log(arr.includes(3));//true
8.6、JavaScript-数组练习
练习1:
1.已知数组[3, 5, 7, 4],获取数组中最大值并打印
let arr = [3, 5, 7, 4];
let max = arr[0];
for (let i = 1; i < arr.length; i++){
if (arr[i] > max){
max = arr[i];
}
}
console.log(max);
练习2:
要求用户输入3个0-9的数,输出0-9中哪些用户没有输入过
输入的格式:x,y,z
let str = prompt("请输入三个整数,用逗号隔开");
console.log(str);
//字符串的split方法,可以根据传入的参数切割字符串,转换成一个数组之后返回给我们
let arr = str.split(",");//用逗号切割,将值变为数组返回
console.log(arr);
for(let i = 0; i < 10; i++){
if (arr[0] == i || arr[1] == i || arr[2] == i ) {
continue;//后面的代码不会被执行,执行下一次循环
}
console.log(i);
}
练习3:
优化练习2
要求用户输入多个0-9的数,输出0-9中哪些用户没有输入过
输入的格式:x,y,z
let str = prompt("请输入三个整数,用逗号隔开");
console.log(str);//1, 3, 5
//字符串的split方法,可以根据传入的参数切割字符串,转换成一个数组之后返回给我们
let arr = str.split(",");//用逗号切割,将值变为数组返回
console.log(arr);
/*
0 1 2 3 4 5 6 7 8 9
undefined, 666,undefined, 666, undefined, 666, undefined, undefined, undefined, undefined
*/
let res = new Array(10);
for (let i = 0; i < arr.length; i++){
let str = arr[i];
res[str] = 666;
}
for (let i = 0; i < res.length; i++){
if(res[i] === 666){
continue;
}
console.log(i);
}
8.7、JavaScript-数组计数排序
从键盘接受5个0-9的数组,排序后输出
输入的格式x,y,z...
2, 6, 3, 8, 1
方法一:如下
问题:输入重复数字时,代码有问题
let str = prompt("请输入五个整数,用逗号隔开");
let arr = str.split(",");//用逗号切割,将值变为数组返回
let res = new Array(10);
for (let i = 0; i < arr.length; i++){
let str = arr[i];
res[str] = 6;
}
for (let i = 0; i < res.length; i++){
if(res[i] === 6){
console.log(i);
}
}
方法二:解决了方法一的问题,但还有其他问题
问题:负数无法排序。若对0-100的数组排序,要保证数组索引是0-100,需要定义很大的数组,占用内存。
解决方法:8.8见JavaScript-数组选择排序
let str = prompt("请输入五个整数,用逗号隔开");
let arr = str.split(",");
let res = new Array(10);
//数组的fill方法的作用:设置数组中所有元素的值为指定的数据
res.fill(0);//将数组中所有的值写为0
console.log(res);
//2,6,3,8,3
0 1 2 3 4 5 6 7 8 9
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 1, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 1, 0, 0, 0, 1, 0, 0, 0]
[0, 0, 1, 1, 0, 0, 1, 0, 0, 0]
[0, 0, 1, 1, 0, 0, 1, 0, 1, 0]
[0, 0, 1, 2, 0, 0, 1, 0, 1, 0]
for (let i = 0; i < arr.length; i++){
let str = arr[i];//2 6 3 8 3
res[str] = res[str] + 1;// res[2] = 0 + 1;
}
console.log(res);
for (let i = 0; i < res.length; i++){
for (let j = 0; j < res[i]; j++){
// console.log(i);
document.write(i);
}
}
8.8、JavaScript-数组选择排序
从键盘接受4个数字,排序后输出
4,3,-5,1
let str = prompt("请输入4个数字,用逗号隔开");
let arr = str.split(",");
console.log(arr);
for (let i = 0; i < 3; i++){
for(let j = i; j < 3; j++){
// document.write("*")
//console.log(i, j + 1);//对比索引查看逻辑
if (arr[i] > arr[j + 1]) {//a大于b交换位置
let temp = arr[i];
arr[i] = arr[j + 1];
arr[j + 1] = temp;
}
}
//document.write("<br>")
}
console.log(arr);
8.9、JavaScript-数组冒泡排序
从键盘接受4个数字,排序后输出
4,3,-5,1
let str = prompt("请输入4个数字,用逗号隔开");
let arr = str.split(",");
console.log(arr);
for (let i = 0; i < 3; i++){
for(let j = 0; j < 3 - i; j++){
//document.write("*")
console.log(j, j + 1);
if (arr[j] > arr[j + 1]) {//a大于b交换位置
let temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
document.write("<br>")
}
console.log(arr);
8.10、JavaScript-二维数组
1.什么是二维数组
二维数组就是数组的每一个元素又是一个数组,我们就称之为二维数组
let arr = [1, 2, 3]//一维数组
let arr1 = [[1, 2], [3, 5]]//二维数组、
注意点:在定义二维数组的时候,将来需要存储多少个一位数组,就写上所少个[]即可
let all1 = [[],[]];
2.如何操作二维数组
2.1、如何从二维数组中获取数据
数组名称[二维数组索引]——>得到一个一维数组
let arr0 = all[0];
console.log(arr0);//[1, 2]
数组名称[二维数组索引][一维数组索引]——>得到一个一维数组元素
let ele = all[0][1];
console.log(ele);//2
2.2、如何从二维数组中存储数据
数组名称[二维数组索引] = 一维数组;
数组名称[二维数组索引][一维数组索引] = 值;
let all1 = [[],[]];
all1[0] = [1, 3];
console.log(all1);//(2) [Array(2), Array(0)]
all1[1][0] = 2;
console.log(all1);//(2) [Array(2), Array(1)]
3.遍历一个二维数组
let all = [[1, 2], [3, 5]];//二维数组
for (let i = 0; i < all.length; i++){
let subArray = all[i];//取出了二维数组中的每一个一维数组
console.log(subArray);
for(let j = 0; j < subArray.length; j++){
console.log(subArray[j]);
}
}
9、JavaScript-函数
9.1、JavaScript-函数基本概念
1.什么是函数?
函数是专门用于封装代码的,函数是一段可以随时被反复执行的代码块
2.函数格式
function 函数名称(形参列表) {
被封装的代码;
}
3.不使用函数的弊端
3.1、冗余代码太多
3.2、需求变更需要修改很多代码
4.使用函数的好处
4.1、冗余代码变少了
4.2、需求变更需要修改代码变少
9.2、JavaScript-函数定义步骤
1.函数定义的步骤
1.1、书写函数的固定格式
function 函数名称(形参列表){
需要封装的代码;
}
1.2、给函数起一个有意义的名称
1.为了提升代码的阅读性
2.函数名称也是标识符的一种,所以也需要遵守标识符的命名规则和规范
1.3、确定函数的形参列表
看看使用函数的时候是否需要传入一些辅助的数据
1.4、将需要封装的代码拷贝到{}中
1.5、确定函数的返回值
可以通过return 数据;的格式,将函数中的计算结果返回给函数的调用者
//需求:要求计算两个变量的和
function getSum(a, b){//a = num1, b = num2
let res = a + b;//let res = 10 + 20;let res = 30;
//将res返回给函数的调用者
return res;
}
let num1 = 10;
let num2 = 20;
let result = getSum(num1, num2);//let result = res;let result = 30
console.log(result);
9.3、JavaScript-函数的注意点
1.一个函数可以有形参也可以没有形参(零个或多个)
形参:定义函数时函数()中的变量我们就称之为形参
function say() {//没有形参
console.log("hello");
}
say();//hello
function say(name) {//有形参
console.log("hello" + name);
}
say(1);//hello1
2.一个函数可以有返回值也可以没有返回值
function say() {//没有返回值的函数
console.log("hello");
}
say();//hello
function say(a, b) {//有返回值的函数
return a + b;
}
let sum = say(1, 2);
console.log(sum);//3
3.函数没有通过return明确返回值, 默认返回undefined
function say() {//没有明确返回值的函数
console.log(" hello");
return;//写这句或者不写都是undefined
}
console.log(say());//undefined
4.return的作用和break相似, 所以return后面不能编写任何语句(永远执行不到)
function say() {
console.log(" hello");
return;
console.log(" return后面的hello0");
}
say();//hello
5.调用函数时实参的个数和形参的个数可以不相同
什么是实参? 调用函数时传入的数据我们就称之为实参
function say(a, b) {
console.log(a, b);//10 undefined
return a + b;
}
let res = say(10);//这里的10和5是实参.可以使常量或者变量
6.JavaScript中的函数和数组一样, 都是引用数据类型(对象类型)
既然是一种数据类型, 所以也可以保存到一个变量中
将一个函数保存到一个变量中
将来可以通过变量名称找到函数并执行函数
let say = function () {// 将一个函数保存到一个变量中
console.log("hello");
}
say();//hello
9.4、JavaScript-函数arguments
1.因为console.log();也是通过()来调用的,所以log也是一个函数
2.log函数的特点
可以接受1个或多个参数
3.为什么log函数可以接受1个或多个参数
内部的实现原理就用到了arguments
4.arguments的作用
保存所有传递给函数的实参
function f() {
//注意点:每个函数中都有一个叫做arguments的小可爱
//arguments其实是一个伪数组(面向对象的时候再做说明)
//console.log(arguments);//Arguments(3) [11, 10, 30, callee: ƒ, Symbol(Symbol.iterator): ƒ]
//console.log(arguments[0]);//11
let sum = 0;
for (let i = 0; i < arguments.length; i++){
let num = arguments[i];
console.log(num);
sum = sum + num;
}
return sum;
}
let res = f(11, 10, 30);
console.log(res);
9.5、JavaScript-函数扩展运算符-ES6
1.扩展运算符在等号左边
将剩余的数据打包到新的数组中。扩展运算符只能写在最后
let [a, ...b] = [1, 3, 5]
console.log(a, b);1 [3, 5]
2.扩展运算符在等号右边
将数组中的数据解开
let arr1 = [1,3,5];
let arr2 = [1,23,9];
let arr = [...arr1,...arr2];
console.log(arr);//[1, 3, 5, 1, 23, 9]
3.扩展运算符在函数的形参列表中的作用
将传递给函数的所有实参打包到一个数组中。
function f(...values) {
console.log(values);//[10, 20]
let sum = 0;
for (let i = 0; i < values.length; i++){
let num = values[i];
sum = sum + num;
}
return sum;
}
let res = f(10, 20);
console.log(res);//30
注意点:和在等号的左边一样,也只能写在形参列表的最后
function f1(...values, a) {
console.log(a);
console.log(values);//报错:Rest parameter must be last formal parameter
}
f1(10,20,30);
9.6、JavaScript-函数形参默认值-ES6
1.函数如果不传递实参,只有形式参数,那么形式参数的默认值是undefined
function f(a, b) {
console.log(a, b);//undefined undefined
}
f();
2.ES6之前可以通过逻辑运算符来给形参指定默认值
在逻辑或运算中,如果参与运算的不是布尔类型,返回值有一个特点。
格式:条件A || 条件B
如果条件A成立,那么就返回条件A
如果条件A不成立,无论条件B是否成立,都会返回条件B
function f(a, b) {
a = a || "JJ";
b = b || "GG";
console.log(a, b);//JJ GG
}
f();
3.ES6开始,可以直接在形式参数后面通过=指定默认值
function f(a = "JJ", b = "GG") {
console.log(a, b);//JJ GG
}
f();
4.注意点:ES6开始默认值还可以从其它的函数中获取
function f(a = "GG", b = getDefault()) {
console.log(a, b);//JJ GG
}
f();
function getDefault() {
return "JJ";
}
9.7、JavaScript-函数作为参数和返回值
将函数作为其他函数的参数
let say = function () {
console.log("傻子");
}
function test(fn) {
fn();
}
test(say);
将函数作为其他函数的返回值
function test() {
//注意点:在其他编程语言中,函数是不可以嵌套定义的,但是在JavaScript中函数是可以嵌套定义的
let say = function () {
console.log("傻子");
}
return say;
}
let fn = test();//相当于let fn = say;
fn();
9.8、JavaScript-匿名函数
1.什么是匿名函数?
匿名函数就是没有名称的函数
有名称的函数
function say() {
console.log("hello");
}
let say = function () {
console.log(hello);
}
匿名函数
function () {
console.log(hello);
}
2.匿名函数不能只定义,不使用。
3.匿名函数的应用场景
3.1、作为其他函数的参数
function test(fn) {
fn();
}
test(function () {
console.log("123");
})
3.2、作为其他函数的返回值
function test() {
return function () {
console.log("abc");
}
}
let fn = test();
fn();
3.3、作为一个立即执行的函数
(function () {
console.log("jefw");
})();
注意点:如果想让匿名函数立即执行,那么必须使用()将函数的定义包裹起来才可以。
9.9、JavaScript-箭头函数-ES6
1.什么是箭头函数?
箭头函数是ES6中新增的一种定义函数的格式
目的:就是为了简化定义函数的代码
2.在ES6之前如何定义函数
function 函数名称(形参列表) {
需要封装的代码;
}
let 函数名称 = function (形参列表) {
需要封装的代码;
}
function say() {
console.log("hello");
}
say();
3.从ES6开始如何定义函数
let 函数名称 = (形参列表) => {
需要封装的代码;
}
let say1 = () => {
console.log("hello say1");
}
say1();
4.箭头函数的注意点
4.1、在箭头函数中,如果只有一个形参,()可以省略
4.2、在箭头函数中,如果{}中只有一句代码,{}也可以省略
function say3(name) {//es6之前
console.log("hello say3" + name);
}
say3("123");
/* let say4 = (name) => {//ES6
console.log("hello say3" + name);
}*/
let say4 = name => console.log("hello say3" + name);//箭头函数
say4("abc");
9.10、JavaScript-递归函数
需求:要求用户输入密码,判断密码是否正确(假设正确密码是123456)
如果正确,输出“欢迎回来
如果不正确,要求用户重新输入
方法一:
let pwd = -1;
do {
pwd = prompt("请输入密码");
}while (pwd !== "123456");
alert("欢迎回来");*/
方法二:涉及递归
1.什么是递归函数?
递归函数就是在函数中自己调用自己,我们就称之为递归函数。
递归函数在一定程度上可以实现循环的功能
function login() {
//1.接受用户输入的尼玛
let pwd = prompt("请输入密码");
//2.判断密码是否正确
if (pwd !== "123456"){
login();
}
//3.输出欢迎回来
alert("欢迎回来");//假设第三次才输入正确,则alert三次
}
login();
假设第三次才输入正确,则alert三次原因见下图
9.11、JavaScript-函数中变量作用域
1.在JavaScript中定义变量有两种方式
ES6之前:var 变量名称;
ES6开始:let 变量名称;
2.两种定义变量方式的区别
2.1、是否能够定义同名变量
var可以定义,let不可以定义同名变量
2.2、是否能够先使用后定义
var可以先使用后定义(预解析),let不可以
2.3、是否能被{}限制作用域(之前未学作用域的概念,现在不适用)
无论是通过var还是let定义在{}外面都是全局变量
var放在{}内部还是全局变量,let放在{}内部则是局部变量
3.局部作用域、全局作用域、块级作用域
3.1、在任何地方都可以访问到的就是全局作用域。在JavaScript中{}外面的作用域,称之为全局作用域
var和let变量在全局作用域中都是全局变量
3.2、只在固定的代码片段内可访问到的变量,例如函数内部。对应局部作用域(函数作用域)。在JavaScript中函数后面{}中的作用域,称之为“局部作用域”
无论是通过var还是let定义在局部作用域的都是局部变量
3.3、任何一对花括号({和})中的语句集都属于一个块,在这之中定义的所有变量在代码块外都是不可见的,我们称之为块级作用域。在ES6中只要{}没有和函数结合在一起,那么应该是“块级作用域”。ES6之前没有块级作用域。
块级作用域中,var定义的变量是全局变量,let定义的变量是局部变量
4.块级作用域和局部作用域区别
4.1、在块级作用域中通过var定义的变量是全局变量
{
//块级作用域
var num = 123;//全局变量
}
console.log(num);
4.2、在局部作用域中通过var定义的变量是局部变量
function test() {
var value = 666;//局部变量
}
test();
console.log(value);//value is not defined
5、无论是在块级作用域还是局部作用域,省略变量前面的let或者var就会变成一个全局变量。
5.1、验证在块级作用域中
{
var num1 = 678;//全局变量
let num2 = 678;//局部变量
num3 = 678;//局部变量
}
console.log(num1);//678
console.log(num2);//num2 is not defined
console.log(num3);//678
5.1、验证在局部作用域中
function f() {
var num1 = 678;//局部变量
let num2 = 123;//局部变量
num3 = 456;//全局变量
}
f();
console.log(num1);//num1 is not defined
console.log(num2);//num1 is not defined
console.log(num3);//456
9.12、JavaScript-作用域链
- JavaScript代码中至少有一个作用域, 即全局作用域。
- 凡是代码中有函数,那么这个函数就构成另一个作用域。
- 如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域。
- 将这样的所有的作用域列出来,可以形成的结构就称之为作用域链。
注意点:初学者在研究“作用域链”的时候最好将ES6之前和ES6分开研究
ES6以前的作用域链:
1.需要明确:
1.1、ES6之前定义变量通过var
1.2、ES6之前没有块级作用域,只有全局作用域和局部作用域
1.3、ES6之前函数大括号外的都是全局作用域
1.4、ES6之前函数大括号中的都是局部作用域
2.ES6之前作用域链
2.1、全局作用域我们又称之为0级作用域
2.2、定义函数开启的作用域就是1级、2级、3级..作用域
2.3、JavaScript会将这些作用域链链接在一起形成一个链条,这个链条就是作用域链
0 ——> 1 ——> 2 ——> 3 ——> 4
2.4、除0级作用域以外,当前作用域级别等于上一级 + 1
0级作用域中定义的函数,函数开启的就是就是0 + 1 级作用域。
//全局作用域/0级作用域
function f() {
//函数f():在0级作用域中定义,是1级作用域
function f1() {
//函数f1():在1级作用域中定义,是2级作用域
}
}
3.变量在作用域链查找规则
3.1、先在当前找,找到就使用当前作用域找到的
3.2、如果当前作用域中没有找到,就去上一级作用域中查找
3.3、以此类推直到0级为止,如果0级作用域还没找到,就报错。
//全局作用域/0级作用域
var num = 123;
function f() {
//函数f():在0级作用域中定义,是1级作用域
var num = 456;
function f1() {
//函数f1():在1级作用域中定义,是2级作用域
var num = 789;
console.log(num);//789
}
f1();
}
f();
ES6中的作用域链:只是多了开启作用域链的块级作用域。
1.需要明确:
1.1、ES6定义变量通过let
1.2、ES6除了全局作用域和局部作用域,还新增了块级作用域
1.3、ES6虽然新增了块级作用域,但是通过let定义变量并无差异(都是局部变量)
2.ES6作用域链
2.1、全局作用域我们又称之为0级作用域
2.2、定义函数或者代码块都会开启的作用域就是1级、2级、3级..作用域
2.3、JavaScript会将这些作用域链链接在一起形成一个链条,这个链条就是作用域链
0 ——> 1 ——> 2 ——> 3 ——> 4
2.4、除0级作用域以外,当前作用域级别等于上一级 + 1
3.变量在作用域链查找规则
3.1、先在当前找,找到就使用当前作用域找到的
3.2、如果当前作用域中没有找到,就去上一级作用域中查找
3.3、以此类推直到0级为止,如果0级作用域还没找到,就报错。
//全局作用域/0级作用域
let num = 123;
{
//1级作用域
let num = 456;
function f1() {
//2级作用域
let num = 789;
console.log(num);//789
}
f1();
}
9.13、JavaScript-函数预解析
1.什么是预解析?
浏览器在执行JS代码的时候会分成两部分操作:预计西以及逐行执行代码
也就是说浏览器不会直接执行代码,而是加工处理之后再执行
这个加工处理的过程,我们就称之为预解析
2.预解析规则
2.1、将变量声明和函数声明提升到当前作用域最前面,只提升声明,不提升赋值/函数调用
函数声明:包含{}内的代码片段,以下整体都是函数声明
function f() {
console.log("鸽子");
}
2.2、将剩余代码按照书写顺序一次放到后面(先提升var,在提升function。同名除外)
3.注意点:
通过let定义的变量不会被提升(不会被预解析)
4.变量var let的预解析
//预解析之前:
console.log(num);//undefined
var num = 123;
//预解析之后:
var num;
console.log(num);
num = 123;
不会预解析之前:
console.log(num0);// num0 is not defined
let num0 = 456;
5.定义函数的方法及预解析
5.1、ES6之前定义函数的格式
f();
//ES6之前的这种定义函数的格式,是会被预解析的,所以可以提前调用
function f() {
console.log("鸽子");
}
//预解析之后的代码
function f() {
console.log("鸽子");
}
f();
5.2、如果将函数赋值给一个var定义的变量,那么函数不会被预解析,只有变量会被预解析
f1();//f1 is not a function
var f1 = function () {
console.log("gezi");
}
//预解析之后的代码
var f1;//undefined
f1();
f1 = function () {
console.log("gezi");
}
5.3、ES6定义函数的格式,不会被预解析.
f2();//f2 is not defined
let f2 = () =>{
console.log("gezi2");
}
6.预解析案例
6.1.下列程序的执行结果是什么
var num = 123;
fun();
function fun() {
console.log(num);
var num = 666;
}
//1.解析0级作用域代码
var num;
function fun() {
//2.解析1级作用域代码
var num;
console.log(num);
num = 666;
}
num = 123;
fun();//输出结果为undefined
6.2.下列程序的执行结果是什么
var a = 520;
demo();
function demo() {
var b = 748;
console.log(a);
console.log(b);
console.log(c);
var a = 820;
var c = hhh;
}
//1.解析0级作用域代码,将函数、变量的声明放到最前面。其余代码按照书写的顺序依次放在后面
var a;
function demo() {
//2.解析1级作用域代码
var b;
var a;
b = 748;
console.log(a);//当前作用域就近选择变量, var a;undefined
console.log(b);//748
console.log(c);//当前作用域没c,去上一个作用域找,也没有。c is not defined
a = 820;
let c = 'hhh';
}
a = 520;
demo();
6.3、 以下练习只在笔试和面试中有,企业开发中一般没有
在ES6之前没有块级作用域,并且没有讲这两个函数定义到其它的函数中。所以这两个函数应该数据全局作用域。
预解析后后定义的顶盖覆盖先定义的函数,而为什么最终的输出结果是第一个demo最后中的呢?
因为(注意点):
1.在高级浏览器中,不会对{}中定义的函数进行提升(预解析)。代码顺序执行
2.只有在低级浏览器中,才会解析
if (true){
function demo() {
console.log("hello interviewer");
}
}else{
function demo() {
console.log("hello interviewer2");
}
}
demo();
预解析:
function demo() {
console.log("hello interviewer");
}
function demo() {
console.log("hello interviewer2");
}
if (true){ }else{ }
demo();
6.4、 1.下列程序的执行结果是什么
注意点:如果变量名称和函数名称同名,那么函数的优先级高于变量
一定要记住,在企业开发中千万不要让变量名称和函数名称重名
console.log(value);
var value = 123;
function value() {
console.log(valueFunction);
}
console.log(value);
/*
预解析:
function value() {
console.log(valueFunction);
}
console.log(value);//ƒ value() {
console.log(valueFunction);
}
var value;
value = 123;
console.log(value);//123