当前位置: 首页 > news >正文

前端技术(二)——javasctipt 介绍

一、javascript基础

1. javascript简介

⑴ javascript的起源

在这里插入图片描述

⑵ javascript 简史

在这里插入图片描述

⑶ javascript发展的时间线

在这里插入图片描述

⑷ javascript的实现

在这里插入图片描述
在这里插入图片描述

⑸ js第一个代码

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js基础</title><!-- js代码写在script标签中在head里 -->   <script type="text/javascript"> /**控制浏览器弹出一个警告       */alert("弹出一条指令框");/* *让计算机在页面中输出一个内容*document.write()可以向bodyz中输出一个内容*/document.write("向文档(body)写一个内容");/** 向控制台输出一个内容* console.log()的作用是向控制台输出一个内容*/console.log("向控制台输出一个内容");    </script></head>
<body>
</body>
</html>

在这里插入图片描述

2. js编写的位置

⑴ 可以将js代码编写到onclick属性里面

<!-- 1. 可以将js代码编写到onclick属性里面当我们点击按钮的时候,js代码才会执行 -->
<button onclick="alert('你点了我一下~')">点击一下</button>

⑵ 可以将js代码编写到超链接的href属性中

<!-- 2. 可以将js代码编写到超链接的href属性中,这样当我们点击超链接的时候,会执行js代码 -->
<a href="javascript:alert('你又点我我一下~')">你再点我一下</a>
<a href="javascript:;">你也点我一下</a>

⑶ js代码写在script标签中在head里

<!-- 3. js代码写在script标签中在head里 -->  
<script type="text/javascript">alert("我是内部的js代码");
</script>

⑷ 可以将js代码写在外部js文件中,让后通过script标签引入

在这里插入图片描述

alert("我是外部的js代码");
<!-- 4. 可以将js代码写在外部js文件中,让后通过script标签引入写在外部的js文件可以引入到不同的页面中去,也可以利用浏览器的缓存机制这是推荐使用的方法注意:script标签一旦引用了外部的文件,就不能在编写代码了,即使编写了代码,浏览器也会忽略如果需要在script中编写代码,则需要再创建一个script标签用于编写内部的js代码 -->
<script type="text/javascript" src="js/script.js"> </script>
<!-- 3. js代码写在script标签中在head里 -->  
<script type="text/javascript">alert("我是内部的js代码");
</script> 

在这里插入图片描述

3. javascript 基本语法

⑴ 注释

  • 多行注释

    <script type="text/javascript">/*** 多行注释* - 注释中的内容会被解释器忽略* - 可以通过注释来对代码解释说明* - 也可以通过注释来去掉不想执行的代码*/
    </script> 
    
  • 单行注释

    <script type="text/javascript">//单行注释
    </script> 
    

⑵ js严格区分大小写

⑶ 在js中多个空格和换行会被忽略,可以利用这个特点来对代码进行格式化

⑷ js 中每条语句都应该以分号结尾,js中具有自动添加分号的机制,所以如果不写分号解释器会自动添加

4. 字面量和变量

在这里插入图片描述

变量的使用:

  • 先声明后赋值

     <script type="text/javascript">//声明变量 用let或者var声明变量let a;//变量赋值a = 10;console.log(a);</script> 
    
  • 声明和赋值同时进行

    <script type="text/javascript">//声明和赋值同时进行let a = 10;console.log(a);
    </script> 
    

5. 变量和内存结构

 <script type="text/javascript">let a = '哈哈';let b = '哈哈';
</script> 

在这里插入图片描述

6. 常量

除了变量外,在JS中还可以使用const关键字来声明常量,区别于变量,常量只能在初始化时对其赋值,一旦赋值则无法修改。

<script type="text/javascript">const PI = 3.1415926console.log(PI);
</script> 

注意:
在这里插入图片描述

7. 标识符

在这里插入图片描述
关键字列表:

在这里插入图片描述
保留字列表:

在这里插入图片描述

8. 数据类型

在这里插入图片描述

⑴ 数值和大整数

数值就是数字,在JavaScript中数字有两种普通的数值和大整数。

1) 数值

在这里插入图片描述

2) 大整数

在这里插入图片描述

3) 类型检查 typeof

typeof用来检查不同值的类型,它会根据不同的值返回不同的结果

<script type="text/javascript">let a = 10;let b = 100n;console.log(typeof a);console.log(typeof b);
</script> 

在这里插入图片描述
在这里插入图片描述

⑵ 字符串

1)字符串介绍

JavaScript中字符串需要使用引号引起来,单引号和双引号都是可以的,没有本质区别。使用typeof运算符检查一个字符串时会返回"string"。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><script type="text/javascript">let c = '字符串';console.log(typeof c);</script> 
</head>
<body></body>
</html>

在这里插入图片描述

2) javascript 中的转义字符

在这里插入图片描述

3)模板字符串

模板字符串可以用来表示一些比较长的字符串(跨行),且可以直接向字符串中嵌入变量,使用 ` 表示模板字符串,在模板字符串中使用 ${变量}来嵌入变量:

let str = `锄禾日当午
汗滴禾下土
谁知盘中餐
粒粒皆辛苦
`
let name = "孙悟空"
let str = `大家好,我是${name}`

例如:

在这里插入图片描述
在这里插入图片描述

⑶ 其他数据类型

1) boolean 布尔值

在这里插入图片描述

2) 空值 null

在这里插入图片描述

3) undefined未定义

在这里插入图片描述

4) 符号symbol

在这里插入图片描述

注意: 上边所有的原始值都是不可变的类型,值一旦创建就无法修改!

⑷ 类型转换

1)其他类型转换成字符串
① 调用toString()方法,将其他类型转换成字符串
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><script type="text/javascript">let a = 10;console.log(typeof a ,a);a = a.toString();console.log(typeof a,a);</script> 
</head>
<body></body>
</html>

在这里插入图片描述

注意:由于nullundefined没有toString()方法,所以对它两调用toString()方法会报错

② 调用String()函数,将其他类型转换成字符串

对应拥有toString()方法的值调用String()函数时,实际上就是在调用toString()方法。
对于null,则直接转换成"null"
对于undefined,则直接转换成"undefined"

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><script type="text/javascript">let a = 10;console.log(typeof a ,a);a = String(a);console.log(typeof a,a);let b = null;console.log(typeof b,b);b = String(b);console.log(typeof b,b);let c = undefined;console.log(typeof c,c);c = String(c);console.log(typeof c,c);</script> 
</head>
<body></body>
</html>

在这里插入图片描述

2)其他类型转换成数字
① 使用Number()函数来将其他类型转换成数值

转换情况:

  • 字符串转换成数字:
    如果字符串是一个合法的数字,则会自动转换成对应数值的数字类型
    如果不是合法的数字,则转换成NaN
    如果字符串是空串或者纯空格的字符串,则转换为0
  • 布尔值:
    true转换成1,false转换成0
  • null
    null转换成0
  • undefined
    undefined转换为NaN
②使用parseInt()函数来将字符串转换成一个整数

parseInt()将一个字符串转换成一个整数,解析时,会自左向右读取一个字符串,直到读取到字符串中所有有效的整数

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><script type="text/javascript">let a = '23.222';a = parseInt(a);</script> 
</head>
<body></body>
</html>

在这里插入图片描述

可以用parseInt()来对一个数字进行取整

③ 使用parseFloat()函数来将字符串转换成一个浮点小数

parseFloat()将一个字符串转换成一个小数,解析时,会自左向右读取一个字符串,直到读取到字符串中所有有效的浮点小数

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><script type="text/javascript">let b = '33.231';b = parseFloat(b);console.log(typeof b,b);</script> 
</head>
<body></body>
</html>

在这里插入图片描述

3)其他类型转换成布尔值

使用Boolean()函数来将其他类型转换成布尔类型
在这里插入图片描述

4) 类型转换总结
  • 转换为字符串
    显式转换
    String()
    隐式转换
    +""

  • 转换为数值
    显式转换
    Number()
    隐式转换
    +

  • 转换为布尔值
    显式转换
    Boolean()
    隐式转换
    !!

8. 运算符

运算符用来对一个或多个值进行运算并返回运算结果。比如,+就是一个运算符,用来求两个数的和。let a = 1 + 1,变量的a的值是2。

⑴ 算数运算符

在这里插入图片描述

//示例:
1 + 1 // 2
true + false //1
1 + "1" // "11"
10 % 3 // 1
2 ** 3 // 8

⑵ 赋值运算符

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><script type="text/javascript">// let a = null;let a = 10;a ??= 100;console.log(a);</script> 
</head>
<body></body>
</html>

在这里插入图片描述

⑶ 一元的+-

  • + 一元的加,正号
  • 一元的减,负号

⑷ 自增和自减

  • ++ 自增
  • --自减

注意:
自增会使变量立刻增加1,自增分为前自增++a和后自增a++,前自增会在自增后返回新值,后自增会在自增以后返回旧值,自减同理。

⑸ 逻辑运算符

  • ! 逻辑非
    在这里插入图片描述

  • && 逻辑与
    && 逻辑与

    1. 可以对两个值进行与运算
    2. &&左右都为true时,则返回true,否则返回false
    3. 与运算是短路的与,如果第一个值为false,则不看第二个值
    4. 与运算是找false的,如果找到false则直接返回,没有false才会返true
    5. 对于非布尔值进行与运算,它会转换为布尔值然后运算但是最终会返回原值, 如果第一个值为false,则直接返回第一个值如果第一个值为true,则返回第二个值
      在这里插入图片描述
  • || 逻辑或

    || 逻辑或

    1. 可以对两个值进行或运算
    2. ||左右有true时,则返回true,否则返回false
    3. 或运算也是短路的或,如果第一个值为true,则不看第二个值
    4. 或运算是找true,如果找到true则直接返回,没有true才会返回false
    5. 对于非布尔值或运算,它会转换为布尔值然后运算,但是最终会返回原值,如果第一个值为true,则返回第一个如果第一个值为false,则返回第二个
      在这里插入图片描述

注意:
逻辑与运算,在运算时会先检查第一个值是否是false,如果是false直接返回第一个,否则返回第二个。逻辑或正好相反,在运算时会先检查第一个值是否是true,如果是true则返回第一个,否则返回第二个。

false && true // false
0 && true // 0
true || false // true
1 || 2 // 1

⑹ 关系运算符

  • > 大于
  • >= 大于等于
  • < 小于
  • <= 小于等于
  1. 关系运算符和后边的相等运算符都用来比较两个值的关系是否成立,关系成立时返回true,否则返回false
  2. 比较非数值时,会先转换为数值然后比较。如果两侧的值都是字符串,则会逐位比较字符串的Unicode编码
1 < 5 // true
1 < '5' // true
'11' < '5' // true 

⑺ 相等运算符

  • == 相等运算符
    相等运算符,用来比较两个值是否相等
    使用相等运算符比较两个不同类型的值时,它会将其转换为相同的类型(通常转换为数值)然后再比较,类型转换后值相同也会返回true
    nullundefined进行相等比较时会返回true,NaN不和任何值相等,包括它自身
    在这里插入图片描述

  • === 全等运算符
    全等运算符,用来比较两个值是否全等。它不会进行自动的类型转换,如果两个值的类型不同直接返回false,nullundefined进行全等比较时会返回false
    在这里插入图片描述

  • != 不等运算符
    用来检查两个值是否不等,会自动进行类型转换

  • !== 不全等运算符
    用来检查两个值是否不等,不会自动进行类型转换

在这里插入图片描述

⑻ 条件运算符

condition ? exprIfTrue : exprIfFalse 三元运算符
执行顺序:

条件表达式 ?表达式1:表达式2

条件运算符在执行时,会先对条件表达式进行求值判断,如果结果为true,则执行表达式1如果结果为false,则执行表达式2

在这里插入图片描述

⑼ 运算符的优先级

在这里插入图片描述

9. 流程控制语句

⑴ 代码块

使用 {}来创建代码块,代码块可以用来对代码进行分组。同一个代码中的代码,就是同一组代码,一个代码块中的代码要么都执行要么都不执行。

1) let与var的区别

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><script type="text/javascript">{var a = 'a';let b = 'b';}console.log(a);console.log(b);</script> 
</head>
<body></body>
</html>

在这里插入图片描述

⑵ if语句

1) 语法

if(条件表达式){
 语句…
}

2) 执行流程
  • if语句在执行时会先对if后的条件表达式进行求值判断,如果结果为true,则执行,if后的语句如果为false则不执行

  • if语句只会控制紧随其后的那一行代码,如果希望可以控制多行代码,可以使用{}将语句扩起来最佳实践:即使if后只有1行代码,我们也应该写代码块,这样结构会更加的清晰

  • 如果if后添加的表达式不是布尔值,则会转换成布尔值然后在进行运算

    if(100){alert('执行了if');//会执行
    }
    
3) if-else语句
1) 语法

if(条件表达式){
  语句…
}else if(条件表达式){
  语句…
}

2) 执行流程

if-else执行时,先对条件表达式进行求值判断,如果结果为true 则执行if后的语句,如果结果为false 则执行else后的语句

在这里插入图片描述

⑶ switch语句

1) 语法

switch(){
 case 表达式:
   代码…
   break;
  case 表达式:
   代码…
   break;
 case 表达式:
   代码…
   break;
 default:
   代码…
   break;
}

这里是引用

2) 执行流程

switch语句在执行时,会依次将switch后的表达式和case后的表单式进行全等比较
如果比较结果为true,则自当前case处开始执行代码
如果比较结果为false,则继续比较其他case后的表达式,直到找到true为止
如果所有的比较都是false,则执行default后面的语句

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><script type="text/javascript">let num = +prompt('请输入一个数字~');switch(num){case 1:alert('壹');break;case 2:alert('贰');break;case 3:alert('叁');break;default:alert('其他数字');break;}</script> 
</head>
<body></body>
</html>

在这里插入图片描述

总结:
switch语句和if语句的功能是重复的,switch能做的事if也能做,反之亦然,它们最大的不同在于,switch在多个全等列断时,结构比较清晰

10. 循环语句

通过循环语句可以使指定的代码反复执行

⑴ while语句

1) 语法

while(条件表达式){
  语句…
}

通常情况下,编写一个循环体需要三个要素:

  1. 初始化表达式(初始化变量)
  2. 条件表达式(设置循环运行的条件)
  3. 更新表达式(修改初始化变量)
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><script type="text/javascript">//1.初始化表达式(初始化变量)let i = 0;//2.条件表达式(设置循环运行的条件)while(i < 5){console.log(i);//更新表达式(修改初始化变量)i++;}</script> 
</head>
<body></body>
</html>

在这里插入图片描述

2) 执行流程

while语句在执行的时候,会先对条件表达式进行判断,如果结果为true,则执行循环体,执行完毕后继续判断。如果为true,则再次执行循环体,执行完毕后,继续判断,如此反复,直到条件表达式结果为false时,循环结束。

⑵ do-while 语句

1) 语法

do{
  语句…
}while(条件表达式)

2) 执行顺序

do-while语句在执行中,会先执行do后面的循环体,执行完毕后,会对while后的条件表达式进行判断,如果为false,则循环体终止,如果为true,则继续执行循环体,以此类推。

do-while和while的区别
do-while是先执行后判断
while是先判断后执行

⑶ for循环

1) 语法

for(初始化表达式;条件表达式;更新表达式){
   语句…
}

2)执行流程

1.执行初始化表达式,初始化变量
2.执行条件表达式,判断循环是否执行(true执行,false终止)
3.判断结果为true,则执行循环体
4.执行更新表达式,对初始化变量进行修改
5. 重复2,知道判断为false为止

⑷ break和continue

  • break
    1.break用来终止switch和循环体
    2.break执行后当前的switch或循环会立刻终止
  • continue
    continue用来跳过当次循环体

11. 对象

对象是js中的一种复合类型的属性,它相当于一个容器,在对象中可以存储各种不同类型的数据。

⑴ 对象的基本操作

1) 创建对象

let obj = new Object();
可以简写成:let = Object();

2) 向对象中添加属性

对象中可以存储多个各种类型的数据,对象中存储的数据,我们称为属性

对象.属性名 = 属性值

3) 读取对象中的数据

对象.属性名

如果读取的是对象中没有的属性,不会报错,而是返回undefined

4) 修改属性值

对象.属性名 = 属性值

5) 删除属性

delete obj.name

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><script type="text/javascript">let obj = Object();obj.name = '张三';obj.age = 19;obj.sex = '男';console.log(obj);console.log(obj.age);obj.age = 18;console.log(obj.age);delete obj.age;console.log(obj.age);</script> 
</head>
<body></body>
</html>

在这里插入图片描述

⑵ 对象的属性

1)属性名
① 属性名的命名
  • 通常属性名就是一个字符串,所以属性名可以是任何值,没有什么特殊要求,但是如果你的属性名太特殊了,不能直接使用,需要使用[]来设置,虽然如此,但是我们还是强烈建议属性名也按照标识符的规范命名

    <!DOCTYPE html>
    <html lang="en">
    <head><meta charset="UTF-8"><title>js讲解</title><script type="text/javascript">let obj = Object();obj.name = "张三";obj.if = "哈哈哈";//不建议obj.let="嘻嘻";//不建议obj["11233q@#$@!"] = "呵呵呵";//不建议console.log(obj);console.log(obj["11233q@#$@!"]);</script> 
    </head>
    <body></body>
    </html>
    

    在这里插入图片描述

  • 也可以使用符号(Symbol)作为属性名来添加属性,获取这种属性时,务必使用Symbol。
    使用Symbol添加的属性。通常是那些不希望被外界访问的属性。

    <!DOCTYPE html>
    <html lang="en">
    <head><meta charset="UTF-8"><title>js讲解</title><script type="text/javascript">let obj = Object();obj.name = "张三";let mySymbol = Symbol();//使用Symbol作为属性名obj[mySymbol] = "通过Symbol作为的属性名";console.log(obj);console.log(obj[mySymbol]);</script> 
    </head>
    <body></body>
    </html>
    

    在这里插入图片描述

② 通过.[]添加属性的两种方式
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><script type="text/javascript">let obj = Object();//通过.的方式添加属性obj.name = "张三";//通过[]""添加属性obj["age"] = 18;//通过变量和[]添加属性let str = "address";obj[str] = "中国";//通过.添加属性obj.str = "haha";//使用.添加属性的时候不能使用变量,这个等价于obj["str"] = "haha"console.log(obj);</script> 
</head>
<body></body>
</html>

在这里插入图片描述

2) 属性值

对象的属性值可以是任意的数据类型,也可以是一个对象

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><script type="text/javascript">let obj = Object();obj.a = 123;obj.b = "hello";obj.c = true;obj.d = 123n;obj.e = Object();obj.e.name = "张三";obj.e.age = 13;console.log(obj);console.log(obj.e);console.log(obj.e.name);</script> 
</head>
<body></body>
</html>

在这里插入图片描述

2) typeof in 两个运算符
  • typeof判断数据类型

  • in 判断 对象中是否存在某个属性,如果存在返回true,否则返回false。语法为:属性名 in 对象

    <!DOCTYPE html>
    <html lang="en">
    <head><meta charset="UTF-8"><title>js讲解</title><script type="text/javascript">let obj = Object();obj.a = 123;obj.b = "hello";obj.c = true;obj.d = 123n;obj.e = Object();obj.e.name = "张三";obj.e.age = 13;console.log(obj);console.log(obj.e);console.log(obj.e.name);console.log(typeof obj);console.log("name" in obj);console.log("name" in obj.e);</script> 
    </head>
    <body></body>
    </html>
    

    在这里插入图片描述

⑶ 对象的字面量

可以使用{}之间创建对象,使用{}所创建的对象可以直接向对象中添加属性

语法
{
  属性名:属性值,
  [属性名]:属性值
}

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><script type="text/javascript">let mySymbol = Symbol();let obj = {name:"张三",age:18,["gender"]:"男",[mySymbol]:"符号类型",hello:{a:"哈哈哈"}};console.log(obj);</script> 
</head>
<body></body>
</html>

在这里插入图片描述

⑷ 枚举对象中的属性for-in

枚举对象中的属性是指将对象中的属性全部获取

  • 语法

    for(let propName in 对象){
      语句…
    }

    for-in的循环体会执行多次?有几个属性就会执行几次,每次执行时,都会将一个属性名赋值给我们所定义的变量

    注意:并不是所有的属性都可以枚举,比如使用符号添加的属性

    <!DOCTYPE html>
    <html lang="en">
    <head><meta charset="UTF-8"><title>js讲解</title><script type="text/javascript">let obj = {name:"张三",age:18,["gender"]:"男",[Symbol()]:"符号类型",//符号类型的属性不能被枚举hello:{a:"哈哈哈"}};for(let propName in obj){console.log("属性名:"+propName,"属性值:"+obj[propName]);}</script> 
    </head>
    <body></body>
    </html>
    

    在这里插入图片描述

⑸ 可变类型

1)原始值介绍

原始值都属于不可变类型,一旦创建就无法修改,在内存中不会创建重复的原始值。

let a = 10;
a = 12;

在这里插入图片描述

2)对象在内存中的情况
let obj = Object();
obj.name = "猪八戒";
obj.age = 18;

在这里插入图片描述

在这里插入图片描述

let obj = Object();
obj.name = "猪八戒";
obj.age = 18;
obj.name = "孙悟空"

在这里插入图片描述
在这里插入图片描述
对象属于可变类型,对象创建完成之后,可以任意添加、删除、修改对象中的属性。

注意:
① 当对两个对象进行相等或者全等比较时,比较的是对象的内存地址。
② 如果两个变量同时指向一个对象,通过一个变量修改对象时,对另一个对象也会产生影响。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><script type="text/javascript">let obj1 = Object();let obj2 = Object();console.log(obj1 == obj2 );let obj = {name:"张三",age:18};obj1 = obj;obj2 = obj;console.log(obj1);console.log(obj2);console.log(obj1 == obj2);obj1.name = "李四";console.log(obj1);console.log(obj2);</script> 
</head>
<body></body>
</html>

在这里插入图片描述

⑹ 方法(method)

当一个对象的属性指向一个函数,那么我们就称这个函数是该对象的方法。调用函数就称为调用对象的方法

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><script type="text/javascript">let obj = {};obj.name = "孙悟空";//函数可以成为一个对象的属性obj.sayHello = function(){console.log("你好啊~");}console.log(obj);obj.sayHello();</script> 
</head>
<body></body>
</html>

在这里插入图片描述

12. 函数(Function)

函数是一个对象,它具有其他对象的所有功能,函数中可以存储代码,且可以在需要时调用这些代码。

⑴ 语法

function 函数名(){
  语句…
}

⑵ 函数简单的创建和调用

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><script type="text/javascript">function fn(){console.log("函数内容");}fn();console.log(typeof fn);</script> 
</head>
<body></body>
</html>

在这里插入图片描述

调用函数就是执行函数中存储的代码,使用typeof检查函数时会返回function。

⑶ 函数的创建方式

1) 函数声明

function 函数名([参数]){
 语句…
}

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><script>function fn(){console.log("声明式函数定义~");}fn();console.log(typeof fn);</script>
</head>
<body></body>
</html>
2) 函数表达式

const fn = function([参数]){
 语句…
}

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><script>const fn =  function(){console.log("函数表达式定义~");}fn();console.log(typeof fn);</script>
</head>
<body></body>
</html>

在这里插入图片描述

3)箭头函数

const fn = ([参数])=>{
 语句…
}
如果{}只有一行,可以省略大括号。
const fn = ([参数])=>console.log(“箭头函数定义~”);

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><script>const fn = ()=>{console.log("箭头函数定义~");}fn();console.log(typeof fn);</script>
</head>
<body></body>
</html>

在这里插入图片描述

⑷ 函数参数

1) 形式参数
  • 在定义函数时,可以在函数中指定数量不等的形式参数(形参)
  • 在函数中定义形参,就相当于在函数内部声明了对应的变量但是没有赋值
2) 实际参数
  • 在调用函数时,可以在函数()中传递数量不等的实参
  • 实参会赋值给对应的形参
  • 参数
    ○ 如果实参和形参数量相同,则对应的实参赋值给对应的形参
    ○ 如果实参多余形参,则多余的实参不会使用
    ○ 如果形参多余实参,则多余的形参为undefined
3) 参数类型

js中不会检查参数的类型,可以传递任何类型的值作为参数

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><script>const sum =  function(a,b){console.log(a + b);}sum(1,7);</script>
</head>
<body></body>
</html>

在这里插入图片描述

4) 箭头函数的参数和参数默认值
① 箭头函数的参数
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><script>const fn = (a,b)=>{console.log("a=",a);console.log("a=",b);}fn(3,4);</script>
</head>
<body></body>
</html>

在这里插入图片描述

② 当箭头函数的()内只有一个参数的时候,()可以省略
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><script>const fn = a =>{console.log("a=",a);}fn(8888888);</script>
</head>
<body></body>
</html>

在这里插入图片描述

③ 定义函数的时候可以给参数指定默认值,默认值会在没有指定实参的时候生效
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><script>function fn(a = 1,b = 2,c = 3){console.log("a = ", a);console.log("b = ",b);console.log("c = ",c);}fn(9,4);</script>
</head>
<body></body>
</html>

在这里插入图片描述

⑸ 使用对象作为参数

1) 修改对象的时候,如果有其他变量指向该对象,则所有指向该对象的变量都会受到影响
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><script>function fn(a){//修改对象的时候,如果有其他变量指向该对象,则所有指向该对象的变量都会受到影响a.name = "猪八戒";console.log(a);}//创建一个对象let obj = {name:"孙悟空"};//对象可以作为一个实参传递,传递实参时,传递的并不是变量本身,而是变量中存储的值fn(obj);console.log(obj);</script>
</head>
<body></body>
</html>

在这里插入图片描述

2) 修改变量的时候,只会影响当前变量的值
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><script>function fn(a){//修改变量的时候,只会影响当前变量的值a = {};a.name = "猪八戒";console.log(a);}//创建一个对象let obj = {name:"孙悟空"};//对象可以作为一个实参传递,传递实参时,传递的并不是变量本身,而是变量中存储的值fn(obj);console.log(obj);</script>
</head>
<body></body>
</html>

在这里插入图片描述

3) 函数每次调用都会重新创建默认值
① 如果对象在()内创建,则函数每次调用都会重新创建默认值
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><script>//函数每次调用都会重新创建默认值function fn(a = {name:"孙悟空"}){console.log("a = ",a);a.name = "猪八戒";console.log("a = ",a);}fn();fn();</script>
</head>
<body></body>
</html>

在这里插入图片描述

② 如果对象在()创建,则函数每次调用都访问同一个对象
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><script>//函数每次调用都会重新创建默认值let obj = {name:"孙悟空"};function fn(a = obj){console.log("a = ",a);a.name = "猪八戒";console.log("a = ",a);}fn();fn();</script>
</head>
<body></body>
</html>

在这里插入图片描述

⑹ 使用函数作为参数

在js中,函数也是一个对象(一等函数),别的对象能做的事情函数也能做。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><script type="text/javascript">function fn(a){console.log("a = ",a);a();}let obj = {name:"孙悟空"};function fn1(){console.log("我是fn1函数");}fn(fn1);fn(function(){console.log("我是匿名函数~");});fn(()=>console.log("我是箭头函数~"));</script> 
</head>
<body></body>
</html>

在这里插入图片描述

⑺ 函数的返回值

在函数中,可以通过return关键字来指定函数的返回值,返回值就是函数的执行结果,函数调用完毕返回值便会作为结果返回。
任何值都可以作为返回值使用(包括对象和函数之类)
如果return后不跟任何值,则相当于返回undefined,如果不写return,那么函数的返回值依然是undefined
return一执行函数立即结束

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><script type="text/javascript">function fn(){return 1+2;}let sum = fn();console.log("sum = ",sum);</script> 
</head>
<body></body>
</html>

在这里插入图片描述

⑻ 箭头函数的返回值

箭头函数的返回值可以直接写在箭头后
如果直接在箭头后设置对象字面量为返回值时,对象字面量必须用()`括起案

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><script type="text/javascript">const sum = function fn(a,b){return a+b;}let result = sum(1,345);console.log(result);const addResult = (a,b)=>  a + b;let rs = addResult(345,543);console.log(rs);const objFun = function(){return {name:"张三"};}let obj = objFun();console.log(obj);const objresult = ()=>({name:"李四"});objrs = objresult();console.log(objrs);</script> 
</head>
<body></body>
</html>

在这里插入图片描述

⑼ 作用域(scope)

作用域指的是一个变量的可见区域

1)全局作用域和局部作用域

作用城有两种:
全局作用域和局部作用域

① 全局作用域
  • 全局作用域在网页运行时创建,在网页关闭时候销毁
  • 所有直接编写到<script>标签中的代码都位于全局作用域中
  • 全局作用域中的变量是全局变量,可以在任意位置访问
② 局部作用域
  • 块作用域
    ○ 块作用域一种局部作用城
    ○ 块作用域在代码块执行时创建。代码块执行完毕它就销毁
    ○ 在块作用域中声明的变量是局部变量。只能在块内部访问,外部无法访问

  • 函数作用域
    ○ 函数作用域也是一种局部作用域
    ○ 函数作用域在函数调用时产生,调用结来后销毁。
    ○ 函数每次调用都会产生一个全新的函数作用域
    ○ 在函数中定义的变量是局部变量。只能在函数内部访问,外无法访问。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><script type="text/javascript">let a = "我是全局变量";{let b = "我是块中的局部变量";{console.log(b);console.log(a);}}function fn(){let c = "我是函数中的局部变量";}// console.log(b); 无法访问console.log(a);console.log(c); //无法访问</script> 
</head>
<body></body>
</html>

在这里插入图片描述

2) 作用域链

当我们使用一个变量时,JS解释器会优先在当前作用域中寻找变量,
如果找到了则直接使用,如果没找到,则去上一层作用域中寻找,找到了则使用,如果没找到,则继续去上一层寻找,以此类推。如果一直到全局作用域都没找到,则报错xxxis not defined

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><script type="text/javascript">let a =  "全局变量a";{let a = "第一个代码块中的a";{let a = "第二个代码块中的a";console.log(a);}}let b = "全局变量b";function fn(){//let b = "第一个函数中的b";function f1(){//let b = "第二个函数中的b";console.log(b);}f1();}fn();</script> 
</head>
<body></body>
</html>

在这里插入图片描述

⑽ window对象

1)window对象介绍
  • 在浏览器中,浏览器为我们提供了一个window对象,可以直接访问
  • window对象代表的是浏览器窗口,通过该对象可以对浏览器窗口进行各种操作,除此之外window对象还负责存储JS中的内置对象和浏览器的宿主对象
  • window对象的属性可以通过window对象访问,也可以直接访问
  • 函数就可以认为是window对象的方法
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><script type="text/javascript">console.log(window);window.console.log(window);window.a = "哈哈哈";console.log(a);//向window对象中添加的属性会自动成为全局变量   </script> 
</head>
<body></body>
</html>

在这里插入图片描述

2)var声明变量的特点

var 用来声明变量,作用和let相同,但是var不具有块作用域

  • 在全局中使用var声明的变量,都会作为window对象的属性保存
  • 使用function声明的函数,都会作为window的方法保存
  • 使用let声明的变量不会存储在window对象中,而存在一个“秘密的小地方”(无法访问)
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><script type="text/javascript">var b = 20;//等价于window.b = 20;function fn(){console.log("我是fn");}console.log(window.b);window.fn();let c = 33;console.log(window.c);let d = 4;window.d = 5;console.log(d);</script> 
</head>
<body></body>
</html>

在这里插入图片描述

  • 在局部作用域中,如果没有使用varlet声明变量,则变量会自动成为window对象的属性也就是全局变量

    <!DOCTYPE html>
    <html lang="en">
    <head><meta charset="UTF-8"><title>js讲解</title><script type="text/javascript">function fn(){b = 10;}fn();//变量b在函数调用时候被创建console.log(b);//此时的b等价于window.b,在局部作用域中,如果没有使用var或let声明变量,则变量会自动成为window对象的属性也就是全局变量</script> 
    </head>
    <body></body>
    </html>
    

    在这里插入图片描述

⑾ 函数和变量的提升

1)变量的提升

使用var声明的变量,它会在所有代码执行前被声明,所以我们可以在变量声明前就访问变量

3)函数的提升
  • 使用函数声明创建的函数,会在其他代码执行前被创建,所以我们可以在函数声明前调用函数
  • let声明的变量实际也会提升,但是在赋值之前解释器禁止对该变量的访问
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><script type="text/javascript">console.log(a);//只声明了,并没有赋值var a = 11;fn();function fn(){console.log("执行了fn");}</script> 
</head>
<body></body>
</html>

在这里插入图片描述

  • debug介绍

    调试如下代码:

    <!DOCTYPE html>
    <html lang="en">
    <head><meta charset="UTF-8"><title>js讲解</title><script type="text/javascript">console.log(a);var a = 1;console.log(a);function a(){alert(2);}console.log(a);var a = 3;console.log(a);var a = function(){alert(4);}console.log(a);var a;console.log(a);</script> 
    </head>
    <body></body>
    </html>
    

    js中debug的使用

⑿ 立即执行函数(IIFE)

立即执行的是一个匿名函数,并且它只执行一次。

格式

格式一:
(function(){ /* code / }()); // 老道推荐写法
格式二:
(function(){ /
code */ })(); // 当然这种也可以

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><script type="text/javascript">(function(){console.log('我是一个立即执行的函数!');}())</script> 
</head>
<body></body>
</html>

在这里插入图片描述

⒀ 函数this的使用

1) 普通函数中this的使用

函数在执行时,JS解析器每次都会传递进一个隐含的参数,这个参数就叫做 this
this会指向一个对象,this所指向的对象会根据函数调用方式的不同而不同

  • 以函数形式调用时,this指向的是window

  • 以方法的形式调用时,this指向的是调用方法的对象

    <!DOCTYPE html>
    <html lang="en">
    <head><meta charset="UTF-8"><title>js讲解</title><script type="text/javascript">function fn(){console.log("普通函数"+this);}fn();const obj1 = {name:"沙和尚",sayHello:function(){console.log(this);}}const obj2 = {name:"孙悟空",sayHello:function(){console.log(this);}}obj1.sayHello();obj2.sayHello();</script> 
    </head>
    <body></body>
    </html>
    

    在这里插入图片描述

2) 箭头函数的this使用

箭头函数没有自己的this,它的this由外层作用域决定。箭头函数的this与调用它的方式无关

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><script type="text/javascript">function fn(){console.log("fn-->",this);}const fn2 = ()=>{console.log("fn2-->",this);}fn();fn2();const obj = {name:"唐僧",/**fn:fn,fn2:fn2**///可以简写成fn,fn2}obj.fn();obj.fn2();</script> 
</head>
<body></body>
</html>

在这里插入图片描述

⒁ 回调函数(callback)

一个函数的参数也可以是函数,
如果将函数作为参数传递,那么我们就称这个函数为回调函数(callback)

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>/*一个函数的参数也可以是函数,如果将函数作为参数传递,那么我们就称这个函数为回调函数(`callback`)*/class Person {constructor(name,age){this.name = name;this.age = age;} }const personArr =[new Person("孙悟空",18),new Person("沙和尚",38),new Person("红孩儿",8),new Person("白骨精",16)];//将回调函数作为参数传给filter函数function filter(arr, cb){const newArr= [];for(let i=0;i< arr.length; i++){//将回调函数的结果作为条件if(cb(arr[i])){newArr.push(arr[i]);}}return newArr;} //设置回调函数function callbackfn(obj){return obj.name === "孙悟空";}let result = filter(personArr,callbackfn);console.log(personArr);console.log(result);</script>
</head>
<body></body>
</html>

在这里插入图片描述

⒂ 高阶函数

如果一个函数的参数或返回值是函数,则这个函数就称为高阶函数。
为什么要将函数作为参数传递?(回调函数有什么作用?)
将函数作为参数,意味着可以对另一个函数动态的传递代码

① 参数是函数的高阶函数
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>/*一个函数的参数也可以是函数,如果将函数作为参数传递,那么我们就称这个函数为回调函数(`callback`)如果一个函数的参数或返回值是函数,则这个函数就称为高阶函数*/class Person {constructor(name,age){this.name = name;this.age = age;} }const personArr =[new Person("孙悟空",18),new Person("沙和尚",38),new Person("红孩儿",8),new Person("白骨精",16)];//将回调函数作为参数传给filter函数,filter称之为高阶函数function filter(arr, cb){const newArr= [];for(let i=0;i< arr.length; i++){//将回调函数的结果作为条件if(cb(arr[i])){newArr.push(arr[i]);}}return newArr;} /*设置回调函数(通常不会这么设置回调函数,回调函数一般都是匿名的)function callbackfn(obj){return obj.name === "孙悟空";}let result = filter(personArr,callbackfn);*/let result = filter(personArr,obj =>obj.name === "沙和尚");console.log(personArr);console.log(result);result = filter(personArr,obj =>obj.age <18);console.log(personArr);console.log(result);</script>
</head>
<body></body>
</html>

在这里插入图片描述

② 返回值为函数的高阶函数
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>/*希望在someFn()函数执行时,可以记录一条日志在不修改原函数的基础上,为其增加记录日志的功能可以通过高阶函数,来动态的生成一个新函数*/function someFn(){return "hello";}function outer(cb){return ()=>{console.log("记录日志~~~~~");return cb();}}let rs = outer(someFn);console.log(rs);</script>
</head>
<body></body>
</html>

在这里插入图片描述

⒃ 闭包的介绍

① 什么是闭包:

闭包就是能访问到外部函数作用域中变量的函数

② 什么时候使用:

当我们需要隐藏一些不希望被别人访问的内容时就可以使用闭包

③ 构成闭包的要件:

1.函数的嵌套
2.内部函数要引用外部函数中的变量
3.内部函数要作为返回值返回

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>function outer(){let num = 0;//位于函数作用域中return ()=>{num++;console.log(num);}}let newFn = outer();console.log(newFn);</script>
</head>
<body></body>
</html>

在这里插入图片描述

④ 闭包的生命周期

闭包的生命周期:
1.闭包在外部函数调用时产生,外部函数每次调用都会产生一个全新的闭包
2.在内部函数去失时销毁(内部函数被垃圾回收了,闭包才会消失)

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>function outer(){let num = 0;//位于函数作用域中return ()=>{num++;console.log(num);}}let newFn = outer();//独立闭包let newFn2 = outer();//独立闭包console.log(newFn());console.log(newFn2());//将内部函数设置为null后,会被垃圾回收掉newFn = null;newFn2 = null;</script>
</head>
<body></body>
</html>

在这里插入图片描述

注意事项:
闭包主要用来隐藏一些不希望被外部访问的内容,
这就意味着闭包需要占用一定的内存空间
相较于类来说,闭包比较浪费内存空间(类可以使用原型而闭包不能)需要执行次数较少时,使用闭包,需要大量创建实例时,使用类

⒄ 递归

调用自身的函数称为递归函数,递归的作用和循环是基本一致

编写递归函数,一定要包含两个要件:
1.基线条件- 递归的终止条件
2.递归条件-如何对问题进行拆分
注意:
递归的作用和循环是一致的,不同点在于,递归思路比较清晰简洁,循环的执行性能比较好
在开发中,一般的问题都可以通过循环解决,也是尽量去使用循环,少用递归。只在一些使用循环解决比较麻烦的场景下,才使用递归

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>/*使用循环解决阶乘问题创建一个函数可以用来求任意数的阶乘 n!=n*(n-1)!*/function factorial(num){//创建一个变量用于记录结果let result = 1;for(let i = 2;i<=num;i++){result = result * i;}return result;}/*使用递归解决阶乘问题用递归改造上面的函数*/function recursion(num){//基线条件if(num === 1){return 1;}//递归条件 n!=n*(n-1)!return num * recursion(num - 1);}</script>
</head>
<body></body>
</html>

在这里插入图片描述

⒅ 函数中的隐藏参数arguments和可变参数

① 函数中的隐藏参数arguments

arguments是函数中又一个隐含参数
arguments是一个类数组对象(伪数组)
和数组相似,可以通过索引来读取元素,也可以通过for循环变量,但是它不是一个数组对象,不能调用数组的方法
arguments用来存储函数的实参
无论用户是否定义形参,实参都会存储到arguments对象中
可以通过该对象直接访问实参

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>function fn(){/*函数中的隐藏参数argumentsarguments是函数中又一个隐含参数arguments是一个类数组对象(伪数组)和数组相似,可以通过索引来读取元素,也可以通过for循环变量,但是它不是一个数组对象,不能调用数组的方法arguments用来存储函数的实参无论用户是否定义形参,实参都会存储到arguments对象中可以通过该对象直接访问实参*/console.log(Array.isArray(arguments));//false ,说明arguments不是一个数组//遍历参数并且打印出来for(let i = 0;i<arguments.length;i++){console.log("参数值:",arguments[i]);}//打印argumentsconsole.log(arguments);}fn(1,3,9);</script>
</head>
<body></body>
</html>

在这里插入图片描述

② 可变参数

可变参数,在定义函数时可以将参数指定为可变参数

  • 可变参数可以接收任意数量实参,并将他们统一存储到一个数组中返回
  • 可变参数的作用和arguments基本是一致,但是也具有一些不同点:
    ○ 可变参数的名字可以自己指定
    ○ 可变参数就是一个数组,可以直接使用数组的方法
    ○ 可变参数可以配合其他参数一起使用
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>/*可变参数,在定义函数时可以将参数指定为可变参数可变参数可以接收任意数量实参,并将他们统一存储到一个数组中返回可变参数的作用和arguments基本是一致,但是也具有一些不同点:○ 可变参数的名字可以自己指定○ 可变参数就是一个数组,可以直接使用数组的方法○ 可变参数可以配合其他参数一起使用*///可变参数的名字可以自己指定,定义一个可变参数为args的函数function fn(...args){console.log(args);}//可变参数就是一个数组,可以直接使用数组的方法//定义一个可变参数的函数,该函数的作用是求可变参数的和并返回function fn2(...num){return num.reduce((a,b)=>a+b,0);}//可变参数可以配合其他参数一起使用,但需要将可变参数写到最后function fn3(a,b,...args){for(value of arguments){console.log(value);}console.log(args);}</script>
</head>
<body></body>
</html>

在这里插入图片描述

call()apply()

函数中this的使用回顾:
根据函数调用方式的不同,this的值也不同:
● 以函数形式调用,this是window
● 以方法形式调用,this是调用方法的对象
● 构造函数中,this是新建的对象
● 箭头函数没有自己的this,由外层作用域决定
通过call和apply调用的函数,它们的第一个参数就是函数的this

调用函数除了通过 函数()这种形式外,还可以通过其他的方式来调用函数
比如,我们可以通过调用函数的call()apply()两个方法来调用函数
函数.call()
函数.apply()
call()apply()除了可以调用函数,还可以用来指定函数中的this
call()apply()的第一个参数,将会成为函数的this

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>/*call()和apply()除了可以调用函数,还可以用来指定函数中的thiscall()和apply()的第一个参数,将会成为函数的this*/function fn(){console.log("函数执行了~,this值为:",this);}const obj = {name:"孙悟空",fn}fn.call();fn.call(obj);fn.apply(console);</script>
</head>
<body></body>
</html>

在这里插入图片描述
call()apply()的区别:
● 通过call()方法调用函数,函数的实参直接在第一个参数后一个一个的列出来
● 通过apply()方法调用函数,函数的实参需要通过一个数组传递

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>function fn(a,b){console.log("a=",a,"b=",b,"函数执行了~,this值为:",this);}const obj = {name:"孙悟空",fn}fn(false,true);//通过call()方法调用函数,函数的实参直接在第一个参数后一个一个的列出来fn.call(obj,"张三","李四");//通过apply()方法调用函数,函数的实参需要通过一个数组传递fn.apply(console,[1,2]);</script>
</head>
<body></body>
</html>

在这里插入图片描述

bind()

函数中this的使用回顾:
根据函数调用方式的不同,this的值也不同:
● 以函数形式调用,this是window
● 以方法形式调用,this是调用方法的对象
● 构造函数中,this是新建的对象
● 箭头函数没有自己的this,由外层作用域决定
通过call和apply调用的函数,它们的第一个参数就是函数的this
● 通过bind()返回的函数,thisbind()第一个参数决定(无法修改)

bind()是函数的方法,可以用来创建一个新的函数
bind()可以为新函数绑定this(绑定this后,this值无法在修改)
bind()可以为新函数绑定参数(绑定参数后,该参数的值不可变)

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>/*bind()是函数的方法,可以用来创建一个新的函数● bind()可以为新函数绑定this(绑定this后,this值无法在修改)● bind()可以为新函数绑定参数(绑定参数后,该参数的值不可变)*/function fn(a,b,c){console.log("a=",a,"b=",b,"c=",c,"函数执行了~,this值为:",this);}const obj = {name:"孙悟空",fn}const newFun = fn.bind(obj,"张三",true);//bind()可以为新函数绑定this(绑定this后,this值无法在修改)//想通过call()修改newFun的this,结果无法修改newFun.call(console);//bind()可以为新函数绑定参数(绑定参数后,该参数的值不可变)//想通过传三个实参的方式修改newFun绑定的参数的值,结果无法修改绑定的参数值newFun(1,2,3);</script>
</head>
<body></body>
</html>

在这里插入图片描述

注意:
箭头函数没有自身的this,它的this由外层作用域决定,也无法通过call()apply()bind()修改它的this值
箭头函数中没有arguments

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>/*● 箭头函数没有自身的this,它的this由外层作用域决定,也无法通过call()、apply()和bind()修改它的this值● 箭头函数中没有arguments*/const fun = ()=>{console.log("函数this值为:",this);//箭头函数中没有argumentsconsole.log(arguments);}const obj = {name:"孙悟空",fun}//箭头函数没有自身的this,它的this由外层作用域决定,也无法通过call()、apply()和bind()修改它的this值fun.apply(obj);</script>
</head>
<body></body>
</html>

在这里插入图片描述

13. js严格模式

js运行代码的模式有两种:

  • 正常模式
    ○ 默认情况下代码都运行在正常模式中,在正常模式,语法检查并不严格。它的原则是:能不报错的地方尽量不报错
    ○ 这种处理方式导致代码的运行性能较差
  • 严格模式
    在严格模式下,语法检查变得严格
    ○ 禁止一些语法
    ○ 更容易报错
    ○ 提升了性能
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><script type="text/javascript">//"use strict" 全局的严格模式a = 10;function fn(){"use strict"//函数的严格模式let a = 10;b = 100;}fn();</script> 
</head>
<body></body>
</html>

在这里插入图片描述

14. 面向对象

⑴ 面向对象简介

  • 类是对象模板,可以将对象中的属性和方法直接定义在类中。定义后,就可以直接通过类来创建对象
  • 通过同一个类创建的对象,我们称为同类对象
    ○ 可以使用instanceof来检查一个对象是否是由某个类创建。如果某个对象是由某个类所创建,则我们称该对象是这个类的实例

语法:

创建类的方式:
① class 类名 {} // 类名要使用大驼峰命名
② const 类名=class {}
创建对象的方式:
通过类创建对象
new 类()

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><script type="text/javascript">//创建一个对象fiveconst five = {//添加属性name:"张三",age:33,heigth:180,weight:100,//添加方法sleep(){console.log(this.name+"睡觉了~");},eat(){console.log(this.name+"吃饭了~");}}</script> 
</head>
<body></body>
</html>

⑵ 属性

类是创建对象的模板,要创建对象的第一件事就是定义类

注意
① 类的代码块中默认就是严格模式
② 类的代码块中是用来设置对象的属性的,不是什么代码都能写

1)实例属性

实例属性只能通过实例去访问

2)静态属性

静态属性只能通过类去访问

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><script type="text/javascript">class Person{/*类的代码块,默认就是严格模式,类的代码块是用来设置对象的属性的,不是什么代码都能写*/name ="孙悟空";//Person的实例属性name p1.name//实例属性只能通过实例访问 p1.ageage = 18;static test ="test静态属性";// 使用static声明的属性,是静态属性(类属性),静态属性只能通过类去访问 Person.test }const p1 = new Person();const p2 = new Person();console.log(p1.name+","+p1.age);console.log(p2.name+","+p2.age);console.log(Person.test);</script> 
</head>
<body></body>
</html>

在这里插入图片描述

⑶ 方法

对象中添加方法有两种方式

方式一

方法名 = function(){
 …
}

方式二

方法名(){
 …
}

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><script type="text/javascript">class Person{name = "孙悟空";/*添加方法的的方式一sayHello = function(){console.log("大家好,我是"+this.name);}*///添加方法(实例方法),实例方法中this就是当提实例sayHello(){console.log("大家好,我是"+this.name);}//静态方法(类方法),通过类来调用。this指向的是当前类static test(){console.log("我是静态方法",this);}}const p1 = new Person();console.log(p1);console.log(p1.sayHello);p1.sayHello();Person.test();</script> 
</head>
<body></body>
</html>

在这里插入图片描述

⑷ 构造函数

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><script type="text/javascript">class Person{name;age;gender;//在类中可以添加一个特殊的方法constructor //该方法我们称为构造函数(构造方法)// 构造函数会在我们调用类创建对象时执行constructor(name,age,gender){//可以在构造函数中,为实例属性进行赋值// 在构造函数中,this表示当前所创建的对象this.name = name;this.age = age;this.gender =gender;}}const p1 = new Person("猪八戒",12,"男");const p2 = new Person("孙悟空",13,"男");const p3 = new Person("唐僧",19,"男");console.log(p1);console.log(p2);console.log(p3);</script> 
</head>
<body></body>
</html>

在这里插入图片描述

⑸ 面向对象的三个特点

封装——安全性
继承——扩展性
多态——灵活性

1)封装
① 封装的基本介绍
  • 对象就是一个用来存储对象的容器
  • 对象不仅存储属性,还要负责数据的安全
  • 直接添加到对象中的属性并不安全,因为他们可以被任意的修改
  • 如何确保数据的安全:
    ○ 私有化数据
     ● 将需要保护的数据设置为私有,只能在内部使用
    ○ 提供settergetter方法来开放对数据的操作
     ● 属性设置私有,通过gettersetter方法操作属性带来的好处
      ■ 可以控制属性的读写权限
      ■ 可以在方法中对属性的值进行验证
  • 封装主要用来保证数据的安全性
② 实现封装的方式
  • 属性私有化,加#

  • 通过gettersetter方法操作属性

    get 属性名(){
      return this.#属性;
    }

    set 属性名(参数){
      this.#属性 = 参数;
    }

    <!DOCTYPE html>
    <html lang="en">
    <head><meta charset="UTF-8"><title>js讲解</title><script type="text/javascript">class Person{//通过使用#开头就变成了私有属性,私有属性只能在类内部访问#name;#age;#gender;constructor(name,age,gender){this.#name = name;this.#age = age;this.#gender =gender;}sayHello(){console.log(this.#name);}//getter方法,用来获取属性getName(){return this.#name;}//setter方法,用来设置属性setName(name){this.#name = name;}}const p1 = new Person("猪八戒",12,"男");console.log(p1);console.log(p1.getName());p1.setName("唐僧")console.log(p1);console.log(p1.getName());</script> 
    </head>
    <body></body>
    </html>
    

    在这里插入图片描述

    settergetter方法的新式写法

    <!DOCTYPE html>
    <html lang="en">
    <head><meta charset="UTF-8"><title>js讲解</title><script type="text/javascript">class Person{//通过使用#开头就变成了私有属性,私有属性只能在类内部访问#name;#age;#gender;constructor(name,age,gender){this.#name = name;this.#age = age;this.#gender =gender;}sayHello(){console.log(this.#name);}//getter方法,用来获取属性/* 通过老式的getter方法来获取属性getName(){return this.#name;}*///通过新式的getter方法来获取属性get name(){console.log("执行了新式的getter方法");return this.#name;}/* 通过老式的setter方法来设置属性setName(name){this.#name = name;}*///通过新式的setter方法来设置属性set name(name){console.log("执行了新式的setter方法");this.#name = name;}}const p1 = new Person("猪八戒",12,"男");console.log(p1);//通过  对象.属性 的方式来调用getter方法console.log(p1.name);//通过 对象.属性 的方式来调用setter方法p1.name = "唐僧";console.log(p1);console.log(p1.name);</script> 
    </head>
    <body></body>
    </html>
    

    在这里插入图片描述

2)多态

同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。
在JS中不会检查参数的类型,所以这就意味着任何数据都可以作为参数传递。要调用某个函数,无需指定的类型,只要对象满足某些条件即可。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><script type="text/javascript">class Person{constructor(name){this.name = name;}}class Dog{constructor(name){this.name = name;}}function sayHello(obj){console.log("Hello,"+obj.name);}const dog = new Dog("旺财");const person = new Person("张三");sayHello(dog);sayHello(person);</script> 
</head>
<body></body>
</html>

在这里插入图片描述

3) 继承
  • 可以通过extends关键字来完成继承
  • 当一个类继承另一个类时,就相当于将另一个类中的代码复制到了当前类中(简单理解)
  • 继承发生时,被继承的类称为父类(超类),继承的类称为子类
  • 通过继承可以减少重复的代码,并且可以在不修改一个类的前提对其进行扩展
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><script type="text/javascript">class Animal{constructor(name){this.name = name;}sayHello(){console.log("动物在叫~");}} class Dog extends Animal{//在子类中,可以通过创建同名方法来重写父类的方法sayHello(){console.log("汪汪汪~");}}class Cat extends Animal{//重写构造方法,子类添加新的属性constructor(name,age){//重写构造函数时,构造函数的第一行代码必须为super()super(name);this.age = age;}sayHello(){//调用一下父类的sayHello方法,在子类中可以使用super来引用父类的方法super.sayHello();console.log("喵喵喵~");}}const dog = new Dog("旺财");const cat = new Cat("汤姆");console.log(dog);dog.sayHello();console.log(cat); cat.sayHello();</script> 
</head>
<body></body>
</html>

在这里插入图片描述

⑹ 对象的结构

对象中存储属性的区域实际有两个:

  • 对象自身
    ○ 直接通过对象所添加的属性,位于对象自身中
    ○ 在类中通过 x = y 的形式添加的属性,位于对象自身中
  • 原型对象(prototype)
    ○对象中还有一些内容,会存储到其他的对象里(原型对象)
    ○ 在对象中会有一个属性用来存储原型对象,这个属性叫做__proto__
    原型对象也负责为对象存储属性
     ● 当我们访问对象中的属性时,会优先访问对象自身的属性
     ● 对象自身不包含该属性时,才会去原型对象中寻找
    会添加到原型对象中的情况:
     ● 在类中通过xxx(){}方式添加的方法,位于原型中
     ● 主动向原型中添加的属性或方法
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>js学习</title><script>class Person{name = "孙悟空";age = 18;constructor(){this.add = "花果山";}fun = ()=>{console.log("我是一个箭头方法!");}sayHello() {console.log("你好,我是"+this.name);}}const p = new Person();p.sex = "男";console.log(p);console.log(p.sayHello)p.sayHello = "你好啊";console.log(p.sayHello);</script>
</head>
<body></body>
</html>

在这里插入图片描述

在这里插入图片描述

⑺ 原型对象

1) 访问一个对象的原型对象的方式
  • 对象.__proto__
  • Object.getPrototypeOf(对象)
2) 原型对象中的数据
  • 对象中数据(属性、方法等)
  • constructor (对象的构造函数)
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>js学习</title><script>class Person{name = "孙悟空";sayHello(){console.log("你好,我是"+this.name);}}const p = new Person();console.log(p.__proto__);//访问原型对象的方式一console.log(Object.getPrototypeOf(p));//访问原型对象的方式二console.log(p.__proto__ == Object.getPrototypeOf(p));console.log(p.__proto__.constructor);</script>
</head>
<body>   
</body>
</html>

在这里插入图片描述

3) 原型链

原型对象也有原型,这样就构成了一条原型链,根据对象的复杂程度不同,原型链的长度也不同

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>js学习</title><script>class Person{name = "孙悟空";sayHello(){console.log("你好,我是"+this.name);}}const p = new Person();console.log(p.__proto__);console.log(p.__proto__.__proto__);console.log(p.__proto__.__proto__.__proto__);const obj = {}console.log(obj.__proto__);console.log(obj.__proto__.__proto__);</script>
</head>
<body></body>
</html>

在这里插入图片描述

obj对象的原型链: obj对象 --> 原型 -->null
p对象的原型链: p对象 --> 原型 --> 原型 --> null

注意:
原型链::
读取对象属性时,会优先对象自身属性,
如果对象中有,则使用,没有则去对象的原型中寻找如果原型中有,则使用,没有则去原型的原型中寻找直到找到Object对象的原型 (Object的原型没有原型(为null如果依然没有找到,则返回undefined

  • 作用域链,是找变量的链,找不到会报错
  • 原型链,是找属性的链,找不到会返回undefined
4) 原型的作用

所有的同类型对象它们的原型对象都是同一个,也就意味着同类型对象的原型链是一样

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>class Person{name = "孙悟空";age = 18;sayHello(){console.log("hello,我是"+this.name);}}const p = new Person();const p2 = new Person();console.log(p===p2);//所有的同类型对象它们的原型对象都是同一个,也就意味着同类型对象的原型链是一样console.log(p.__proto__ === p2.__proto__);</script>
</head>
<body></body>
</html>

在这里插入图片描述
原型的作用:
原型就相当于是一个公共的区域,可以被所有该类实例访问,可以将该类实例中,所有的公共属性(方法)统一存储到原型中这样我们只需要创建一个属性,即可被所有实例访问
在对象中有些值是对象独有的,像属性(name,age,gender)。每个对象都应该有自己值,但是有些值对于每个对象来说都是一样的,像各种方法,对于一样的值没必要重复的创建

js中继承就是通过原型来实现的,当集成时,子类的原型就是一个父类的实例

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>class Animal{}class Cat extends Animal{}/*** 继承对象的原型链* cat对象——>父对象Animal对象——>obj对象——>obj对象原型——>null* */const cat = new Cat();console.log(cat);console.log(cat.__proto__);console.log(cat.__proto__.__proto__);console.log(cat.__proto__.__proto__.__proto__);console.log(cat.__proto__.__proto__.__proto__.__proto__);</script>
</head>
<body></body>
</html>

在这里插入图片描述

5) 如何修改原型
① 通过类的实例去修改原型(千万不要这么做!!!)
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>class Person{name = "孙悟空";age = 18;sayHello(){console.log("helllo,我是"+this.name);}}const p = new Person();const p2 = new Person();//通过对象修原型,向原型中添加方法,修改后所有的同类实例都能访问该方法p.__proto__.run = ()=>{console.log("我在跑~");}p.run();p2.run();class Dog{}//直接为对象赋值一个新的原型p.__proto__ = new Dog();console.log(p);console.log(p2);</script>
</head>
<body></body>
</html>

在这里插入图片描述

注意:
千万不要通过类的实例去修改原型

  1. 通过一个对象影响所有同类对象,这么做不合适
  2. 修改原型先得创建实例,麻烦
  3. 危险
② 通过类的prototype属性来修改原型
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>class Person{name = "孙悟空";age = 18;sayHello(){console.log("helllo,我是"+this.name);}}//通过类中的prototype属性修改原型Person.prototype.run = ()=>{console.log("我在跑~");}const p = new Person();const p2 = new Person();console.log(p.__proto__ === Person.prototype);//通过对象获取原型和通过类的属性获取原型是同一个原型console.log(p);p.run();p2.run();</script>
</head>
<body></body>
</html>

在这里插入图片描述

修改原型时,最好通过通过类去修改。好处:
1.一修改就是修改所有实例的原型
2.无需创建实例即可完成对类的修改

在这里插入图片描述

6) instanceofinhasOwn 介绍
instanceof介绍

instanceof用于检查一个对象是否是另一个类的实例
只要原型链上有该实例就会返回true

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>class Animal{}class Dog extends Animal{}const dog = new Dog();console.log(dog instanceof Dog);//trueconsole.log(dog instanceof Animal);//trueconsole.log(dog instanceof Object);//true//dog实例 ->Animal的实例 ->0bject实例 -> Object原型console.log(dog);console.log(dog.__proto__);console.log(dog.__proto__.__proto__);console.log(dog.__proto__.__proto__.__proto__);</script>
</head>
<body></body>
</html>

在这里插入图片描述

in 介绍

使用in运算符检查属性时,无论属性在对象自身还是在原型中,都会返回true

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>class Person{name = "孙悟空";age = 18;sayHello(){console.log("helllo,我是"+this.name);}}const p = new Person();console.log("name" in p);console.log("sayHello" in p);</script>
</head>
<body></body>
</html>

在这里插入图片描述

hasOwn 介绍
  • 对象.hasOwnProperty(属性名)(不推荐使用)
    用来检查一个对象的自身是否含有某个属性 (不包含原型中的属性)

    <!DOCTYPE html>
    <html lang="en">
    <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>class Person{name = "孙悟空";age = 18;sayHello(){console.log("helllo,我是"+this.name);}}const p = new Person();console.log("name" in p);/*** 对象.hasOwnProperty(属性名)(不推荐使用) *  用来检查一个对象的自身是否含有某个属性**/console.log(p.hasOwnProperty("sayHello"));console.log(p.__proto__.__proto__);console.log(p.__proto__.__proto__.hasOwnProperty("sayHello"));//说明hasOwnProperty方法在Object的原型中</script>
    </head>
    <body></body>
    </html>
    

    在这里插入图片描述

  • Object.hasOwn(对象,属性名)
    用来检查一个对象的自身是否含有某个属性 (不包含原型中的属性)

    <!DOCTYPE html>
    <html lang="en">
    <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>class Person{name = "孙悟空";age = 18;sayHello(){console.log("helllo,我是"+this.name);}}const p = new Person();//使用in运算符检查属性时,无论属性在对象自身还是在原型中,都会返回trueconsole.log("name" in p);//trueconsole.log("sayHello" in p);//true/*** Object.hasOwn(对象,属性名)*  用来检查一个对象的自身是否含有某个属性**/console.log(Object.hasOwn(p,"name"));//trueconsole.log(Object.hasOwn(p,"sayHello"));//false</script>
    </head>
    <body></body>
    </html>
    

    在这里插入图片描述

⑻ 旧类(早期类的定义方式)

早期JS中,直接通过函数来定义类

  • 一个函数如果直接调用 xxx()那么这个函数就是一个普通函数
  • 一个函数如果通过new调用 new xxx()那么这个函数就是一个构造函数
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>//通过老的方法定义的类一般会放在一个立即执行函数里面var Person = (function(){/*等价于class Person{}*/function Person(name,age){this.name = name;this.age = age;}//向原型中添加添加属性(方法)Person.prototype.sayHello = () =>{console.log("你好,我是"+this.name);}//添加静态属性Person.staticProperty = "李四";//添加静态方法Person.staticMethod = ()=>{console.log("我是静态方法~");}return Person;})()Person();const p = new Person("张三",19);console.log(p);Person.staticMethod();console.log(Person.staticProperty);</script>
</head>
<body></body>
</html>

在这里插入图片描述

旧类继承的实现

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>var Animal = (function(){function Animal(){}return Animal;})()var Cat = (function(){function Cat(){}//继承AnimalCat.prototype = new Animal();return Cat;})()var cat = new Cat();console.log(cat);console.log(cat instanceof Cat);console.log(cat instanceof Animal);</script>
</head>
<body></body>
</html>

在这里插入图片描述

⑼ new 运算符

new运算符是创建对象时要使用的运算符
使用new时,到底发生了哪些事情:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/0perators/new
当使用new去调用一个函数时,这个函数将会作为构造函数调用,使用new调用函数时,将会发生这些事:
1.创建一个普通的JS对象(0bject对象 {}),为了方便,称其为新对象
2.将构造函数的prototype属性设置为新对象的原型
3.如果构造函数有实参,使用实参来执行构造函数,并且将新对象设置为函数中的this.
4.如果构造函数返回的是一个非原始值,则该值会作为new运算的返回值返回
如果构造函数的返回值是一个原始值或者没有指定返回值,
则新的对象将会作为返回值返回

在JavaScript中,原始值(primitive value)是指那些不是对象的值。
原始类型有五种:undefined、null、boolean、number和string。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>/*1.创建一个普通的JS对象(0bject对象 {}),为了方便,称其为新对象2.将构造函数的prototype属性设置为新对象的原型3.使用实参来执行构造函数,并且将新对象设置为函数中的this.4.如果构造函数返回的是一个非原始值,则该值会作为new运算的返回值返回(千万不要这么做)如果构造函数的返回值是一个原始值或者没有指定返回值,则新的对象将会作为返回值返回*/class MyClass{//var newInstance = {}//1.创建一个普通的JS对象(0bject对象 {}),为了方便,称其为新对象//new newInstance.__proto__ = MyClass.prototype;//2.将构造函数的prototype属性设置为新对象的原型constructor(){return {};}}const myclass = new MyClass();console.log(myclass);</script>
</head>
<body></body>
</html>

在这里插入图片描述

⑽ 对象的分类

在这里插入图片描述

15. 数组(Array)

1)数组的简介

数组也是一种复合数据类型,在数组可以存储多个不同类型的数据数组中存储的是有序的数据,数组中的每个数据都有一个唯一的索引可以通过索引来操作获取数据,数组中存储的数据叫做元素

2) 索引(index)

索引是一组大于0的整数

3)创建数组

通过Array()来创建数组,也可以通过[]来创建数组

4)向数组中添加元素

语法:
数组[索引]= 元素

如果读取了一个不存在的元素,不好报错而是返回undefined

5)数组的属性

length

获取数组的长度

1.实际上length获取的是最大索引+1
2.最大索引+1向数组最后添加元素:
  数组[数组.length]= 元素
3.length是可以修改的

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>const arr = new Array();const arr2 = [10,22,44,88];arr[0]= 10;arr[1]=22;arr[2]=44;arr[3]= 88;arr2[3]=99;arr2[100] = 100; //使用数组时,应该避免非连续数组,因为它性能不好console.log(arr);console.log(arr2);console.log(arr[2]);console.log(arr[100]);//如果读取了一个不存在的元素,不好报错而是返回undefinedconsole.log(typeof arr);//objectconsole.log(arr2.length);//101console.log(arr.length);//4arr[arr.length] = 88;console.log(arr);arr.length = 100;//修改数组长度,比原数组长度大,则通过空值补充console.log(arr);arr.length = 1;//修改数组长度,比元素组小,则删除多余的内容console.log(arr);</script>
</head>
<body></body>
</html>

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>//任何类型的值都可以成为数组中的元素let arr =[1,"hello",true, null,{name:"孙悟空"},( )=>{}]console.log(arr);</script>
</head>
<body></body>
</html>

在这里插入图片描述

注意:
任何类型的值都可以成为数组中的元素,但是创建数组时尽量要确保数组中存储的数据的类型是相同

6)数组的遍历

① 传统for循环遍历数组

遍历数组简单理解,就是获取到数组中的每一个元素

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>let arr = ["孙悟空","猪八戒","沙和尚","唐僧","白骨精"];console.log(arr);//数组正序遍历for(let i = 0;i<arr.length;i++){console.log(arr[i]);}console.log("---------------------------------------");//数组倒序遍历for(let i = arr.length -1;i>=0;i--){console.log(arr[i]);}</script>
</head>
<body></body>
</html>

在这里插入图片描述

for-of 遍历可迭代的对象

在这里插入图片描述

语法:

for(变量 of 可迭代的对象){
  语句…
}

执行流程:

for-of的循环体会执行多次,数组中有几个元素就会执行几次,每次执行时都会将一个元素赋值给变量

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>//for-of遍历数组const arr = ["孙悟空","猪八戒","沙和尚","唐僧","白骨精"];for(let value of arr){console.log(value);}console.log("-------------------------");//for-of遍历字符串for(let value of "hello"){console.log(value);}</script>
</head>
<body></body>
</html>

在这里插入图片描述

7)数组方法的介绍

https://developer.mozilla.org/en-Us/docs/Web/JavaScript/Reference/Global_0bjects/Array

Array.isArray()

用来检查一个对象是否是数组

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>const arr = ["孙悟空","猪八戒","沙和尚","唐僧","白骨精"];console.log(Array.isArray(arr));console.log(Array.isArray("hello"));</script>
</head>
<body></body>
</html>

在这里插入图片描述

at(参数)

可以根据索引获取数组中的指定元素,at可以接收负索引作为参数,表示倒数第几个元素

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>const arr = ["孙悟空","猪八戒","沙和尚","唐僧","白骨精"];console.log(arr.at(1));console.log(arr.at(-2));</script>
</head>
<body></body>
</html>

在这里插入图片描述

concat()

用于拼接两个或多个数组

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>const arr = ["孙悟空","猪八戒","沙和尚","唐僧","白骨精"];const arr2 = ["牛魔王","红孩儿"];console.log(arr.concat(arr2,["铁扇公主","紫霞仙子"]));console.log(arr);</script>
</head>
<body></body>
</html>

在这里插入图片描述

concat()是非破坏性的方法,只会生成新的数组,不会改变原来数组

indexOf()lastIndexOf()
  • indexOf()
    ● 获取元素在数组中第一次出现的索引
    ●参数:
    ○ 要查询的元素
    ○ 查询的起始位置
  • lastIndexOf()
    获取元素在数组中最后一次出现的位置
    ●参数:
    ○ 要查询的元素
    ○ 查询的起始位置
  • 返回值:
    找到了则返回元素的索引,没有找到返回-1
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>const arr = ["孙悟空","猪八戒","沙和尚","唐僧","白骨精","沙和尚"];console.log(arr.indexOf("沙和尚"));console.log(arr.indexOf("沙和尚",3));console.log(arr.lastIndexOf("沙和尚"));console.log(arr.lastIndexOf("沙和尚", 1));</script>
</head>
<body></body>
</html>

在这里插入图片描述

join()

将一个数组中的元素连接为一个字符串

例如:["孙牾空”,“猪八戒”,“沙和尚”,“唐僧”,“沙和尚”]——>"孙悟空,猪八戒,沙和尚,唐僧,沙和尚

参数:
指定一个字符串作为连接符

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>const arr = ["孙悟空","猪八戒","沙和尚","唐僧","白骨精","沙和尚"];console.log(arr.join())console.log(arr.join("——>"))</script>
</head>
<body></body>
</html>

在这里插入图片描述

slice()

用来截取数组(非破坏性方法)

  • 参数:
    ○ 参数1 截取的起始位置(包括该位置)
    ○ 参数2 截取的结束位置(不包括该位置)

○ 第二个参数可以省略不写,如果省略则会一直截取到最后
○ 索引可以是负值,表示倒数第几个
如果将两个参数全都省略,则可以对数组进行浅拷贝(浅复制)

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>const arr = ["孙悟空","猪八戒","沙和尚","唐僧","白骨精","沙和尚"];console.log(arr.slice(1,3));console.log(arr.slice(1,-2));console.log(arr.slice(1));console.log(arr.slice());console.log(arr);</script>
</head>
<body></body>
</html>

在这里插入图片描述

push()

向数组的末尾添加一个或多个元素并返回新数组的长度

pop()

删除数组中最后一个元素,并返回该元素的值

unshift()

向数组的开头添加一个或多个元素并返回新数组的长度

shift()

删除数组中第一个元素,并返回该元素的值

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>/*push()-向数组的末尾添加一个或多个元素并返回新数组的长度pop()-删除数组中最后一个元素,并返回该元素的值unshift()-向数组的开头添加一个或多个元素并返回新数组的长度shift()-删除数组中第一个元素,并返回该元素的值*/const arr = ["唐僧","猪八戒","白骨精"]; console.log(arr);result = arr.push("孙悟空");console.log(arr);console.log(result);result = arr.pop();console.log(arr);console.log(result);result =  arr.unshift("牛魔王");console.log(arr);console.log(result);result =  arr.shift();console.log(arr);console.log(result);</script>
</head>
<body></body>
</html>

在这里插入图片描述

splice()

可以删除、插入、替换数组中的元素

参数:
1.删除的起始位置
2.删除的数量
3.要插入的元素
返回值:
返回被删除的元素

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>/*splice()-可以删除、添加、插入、替换数组中的元素参数:1.删除的起始位置2.删除的数量3.要插入的元素返回值:返回被删除的元素*/const arr = ["唐僧","猪八戒","白骨精"]; console.log("原始数据:",arr);//从索引为1的元素开始删除一个元素result = arr.splice(1,1);console.log(result);console.log("处理后的数据:",arr);//从索引为1的元素开始插入三个元素console.log("原始数据:",arr);result = arr.splice(1,0,"贾宝玉","林黛玉");console.log(result);console.log("处理后的数据:",arr);//从索引为1的元素替换为三个元素console.log("原始数据:",arr);result =  arr.splice(1,1,"牛魔王","铁扇公主");console.log(result);console.log("处理后的数据:",arr);</script>
</head>
<body></body>
</html>

在这里插入图片描述

reverse()

反转数组

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>var arr = ["a","b","c","d"];console.log("原始数组:",arr);arr.reverse();console.log("反转后的数组:",arr);</script>
</head>
<body></body>
</html>

在这里插入图片描述

sort()

sort()用来对数组进行排序(会对改变原数组)
sort()默认会将数组升序排列
参数:
可以传递一个回调函数作为参数,通过回调函数来指定排序规则
(a,b)=>a-b 升序排列
(a,b)=>b-a 降序排列

注意:sort()默认会按照Unicode编码进行排序,所以如果直接通过sort()对数字进行排序可能会得到一个不正确的结果。可以通过传递一个回调函数作为参数解决该问题

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>/*sort()默认会按照Unicode编码进行升序排序,所以如果直接通过sort()对数字进行排序可能会得到一个不正确的结果。可以通过传递一个回调函数作为参数解决该问题*/let arr = [3,0,3,6,10,11,56,5,4,2,8]console.log("排序前的数字:",arr);//按照Unicode编码进行升序排序arr.sort();console.log("排序后的数字:",arr);//通过通过传递一个回调函数作为参数解决按数值大小进行升序排序let arr2 = [3,0,3,6,10,11,56,5,4,2,8]console.log("排序前的数字:",arr2);arr2.sort((a,b)=>a-b);console.log("排序后的数字:",arr2);//通过通过传递一个回调函数作为参数解决按数值大小进行升序排序let arr3 = [3,0,3,6,10,11,56,5,4,2,8]console.log("排序前的数字:",arr3);arr3.sort((a,b)=>b-a);console.log("排序后的数字:",arr3);let arr4 = ['a','c','b','d','f','e'];console.log("排序前的数字:",arr4);arr4.sort();console.log("排序后的数字:",arr4);</script>
</head>
<body></body>
</html>

在这里插入图片描述

forEach()

用来遍历数组
它需要一个回调函数作为参数,这个回调函数会被调用多次
数组中有几个元素,回调函数就会调用几次
每次调用,都会将数组中的数据作为参数传递
回调函数中有三个参数(这三个参数是非必填的):

  • element 当前的元素
  • index 当前元素的索引
  • array 被遍历的数组
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>/*forEach( )用来遍历数组它需要一个回调函数作为参数,这个回调函数会被调用多次数组中有几个元素,回调函数就会调用几次每次调用,都会将数组中的数据作为参数传递回调函数中有三个参数:element 当前的元素index 当前元素的索引array 被遍历的数组*/let arr = ["猪八戒","孙悟空","唐僧","白龙马","沙和尚"];arr.forEach((element,index,arr)=>{console.log(arr);console.log(index,"——>",element)});</script>
</head>
<body></body>
</html>

在这里插入图片描述

filter()

将数组中符合条件的元素过滤并保存到一个新数组中返回
需要一个回调函数作为参数,会为每一个元素去调用回调函数,并根据返回值来决定是否将元素添加到新数组中
非破坏性方法,不会影响原数组
回调函数中有三个参数(这三个参数是非必填的):

  • element 当前的元素
  • index 当前元素的索引
  • array 被遍历的数组
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>/*filter()将数组中符合条件的元素过滤并保存到一个新数组中返回需要一个回调函数作为参数,会为每一个元素去调用回调函数,并根据返回值来决定是否将元素添加到新数组中非破坏性方法,不会影响原数组回调函数中有三个参数(这三个参数是非必填的):element 当前的元素index 当前元素的索引array 被遍历的数组*/let arr = [9,3,4,6,2,0];//获取数组中所有的偶数let result = arr.filter((element)=>element % 2 === 0);console.log("获取数组中所有的偶数:",result);/*回调函数中有三个参数(这三个参数是非必填的):element 当前的元素index 当前元素的索引array 被遍历的数组*/let rs =  arr.filter((element,index,arr) =>{console.log("元素值:",element);console.log("元素下标:",index);console.log("数组:",arr);});</script>
</head>
<body></body>
</html>

在这里插入图片描述

map()

根据当前数组生成一个新数组
需要一个回调函数作为参数,回调函数的返回值会成为新数组中的元素
非破坏性方法不会影响原数组
回调函数中有三个参数(这三个参数是非必填的):

  • element 当前的元素
  • index 当前元素的索引
  • array 被遍历的数组
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>/*map()根据当前数组生成一个新数组需要一个回调函数作为参数,回调函数的返回值会成为新数组中的元素非破坏性方法不会影响原数组回调函数中有三个参数(这三个参数是非必填的):element 当前的元素index 当前元素的索引array 被遍历的数组*/let arr = ["猪八戒","孙悟空","唐僧","白龙马","沙和尚"];//给所有的名字前面加上 "西游记中的人物:"let result = arr.map((element)=>"西游记中的人物:"+element);console.log("获取数组中所有的偶数:",result);/*回调函数中有三个参数(这三个参数是非必填的):element 当前的元素index 当前元素的索引array 被遍历的数组*/let rs =  arr.filter((element,index,arr) =>{console.log("元素值:",element);console.log("元素下标:",index);console.log("数组:",arr);});</script>
</head>
<body></body>
</html>

在这里插入图片描述

reduce()

可以用来将一个数组中的所有元素整合为一个值

参数:

  • 回调函数,通过回调函数来指定合并的规则
  • 可选参数,初始值
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>/*reduce()可以用来将一个数组中的所有元素整合为一个值参数:回调函数,通过回调函数来指定合并的规则可选参数,初始值*/let arr = [1,2,3,4,5,6];//将数组值全部相加后返回let result = arr.reduce((a,b)=>a+b);console.log(result);//添加一个初始值为10,并将数组值全部相加后返回result = arr.reduce((a,b)=>a+b,10);console.log(result);</script>
</head>
<body></body>
</html>

在这里插入图片描述

8)对象的复制

① 对象的拷贝介绍
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>const arr = ["孙悟空","猪八戒","沙和尚"];const arr2 = arr;arr2[1] = "唐僧";//导致arr和arr2都改变了,并不是复制console.log(arr);console.log(arr2);</script>
</head>
<body></body>
</html>

在这里插入图片描述
在这里插入图片描述
通过slice()对象复制

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>const arr = ["孙悟空","猪八戒","沙和尚"];const arr2 = arr.slice();arr2[1] = "唐僧";//只有arr发生复制,arr2改变对arr没有影响console.log(arr);console.log(arr2);</script>
</head>
<body></body>
</html>

在这里插入图片描述
在这里插入图片描述

② 深拷贝和浅拷贝
● 对象的浅拷贝(shallow copy)

通常对对象的拷贝都是浅拷贝,浅拷贝顾名思义,只对对象的浅层进行复制(只复制一层)如果对象中存储的数据是原始值,那么拷贝的深浅是不重要的。浅拷贝只会对对象本身进行复制,不会复制对象中的属性(或元素)

通常用slice()进行浅拷贝

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>const arr = [{name:"孙悟空"},{name:"猪八戒"}];const arr2 = arr.slice();//浅拷贝arr2[1] = {name:"唐僧"};console.log(arr);console.log(arr2);arr[0].name = "牛魔王";console.log(arr);console.log(arr2);</script>
</head>
<body></body>
</html>

在这里插入图片描述

在这里插入图片描述

● 对象的深拷贝(deep copy)

深拷贝指不仅复制对象本身,还复制对象中的属性和元素。因为性能问题,通常情况不太使用深拷贝
通常通过structuredClone(对象)进行深拷贝

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>const arr = [{name:"孙悟空"},{name:"猪八戒"}];const arr2 = arr.slice();//浅拷贝arr2[1] = {name:"唐僧"};console.log(arr);console.log(arr2);arr[0].name = "牛魔王";console.log(arr);console.log(arr2);console.log("-----------------------------------------------------");const array = [{name:"林黛玉"},{name:"贾宝玉"}];const array2 = structuredClone(array);//深拷贝array[1] = {name:"贾乃亮"};console.log(array);console.log(array2);array[0].name = "李小璐";console.log(array);console.log(array2);</script>
</head>
<body></body>
</html>

在这里插入图片描述

在这里插入图片描述

③ 对象复制的其他方式(都是浅拷贝)
● 数组对象通过展开运算符进行复制(...

...(展开运算符)
可以将一个数组中的元素展开到另一个数组中或者作为函数的参数传递,通过它也可以对数组进行浅复制

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>const arr =  ["孙悟空","猪八戒","沙和尚"]/* ...(展开运算符)可以将一个数组中的元素展开到另一个数组中或者作为函数的参数传递,通过它也可以对数组进行浅复制*///const arr3=[arr[0],arr[1],arr[2]]//const arr3 =[...arr];const arr3 =["唐僧",...arr,"白骨精"]console.log(arr)console.log(arr3)function sum(a,b,c){return a+b+c;}const arr4=[10,20,30]//let result =sum(arr4[0],arr4[1],arr4[2]);result =sum(...arr4)console.log(result)</script>
</head>
<body></body>
</html>

在这里插入图片描述

● 对象通过展开运算符(...)和assign()进行复制

对象的复制
0bject.assign(目标对象,被复制的对象)
○ 将被复制对象中的属性复制到目标对象里,并将目标对象返回,也可以使用展开运算符对对象进行复制

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>/*○ 0bject.assign(目标对象,被复制的对象)○ 将被复制对象中的属性复制到目标对象里,并将目标对象返回,也可以使用展开运算符对对象进行复制*/const  obj = {name:"孙悟空",age:19};const obj2 = Object.assign({},obj);const obj3 ={address:"花果山",age:28};const obj4 = Object.assign(obj3,obj);console.log(obj);console.log(obj2);console.log(obj4);console.log("-------------------------------------------");const obj5 = {address:"高老庄",...obj,age:100}console.log(obj5);//将obj中的属性在新对象中展开</script>
</head>
<body></body>
</html>

在这里插入图片描述

二、javascript高级

1. javascript中内嵌对象

⑴ 数组的解构

1)解构赋值
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>/*解构赋值*/const arr = ["张三","李四","王五"];let a,b,c;/* a = arr[0];b = arr[1];c = arr[2]; *///上面的代码等价于[a,b,c] = arr;//解构赋值console.log("a=",a,"b=",b,"c=",c);//解构赋值:声明的变量和赋值的元素一样多let [d,e,f,g] = ["孙悟空","唐僧","沙和尚","猪八戒"]console.log("d=",d,"e=",e,"f=",f,"g=",g);//解构赋值:声明的变量比赋值的元素多let [h,i,j] = ["林黛玉","贾宝玉"];console.log("h=",h,"i=",i,"j=",j);//解构赋值:声明的变量比赋值的元素多   //可以通过赋初始值的方式避免变量值为undefined//如果解构赋值了就为解构赋的值,没有则为初始值let [k,l="黑熊精",m="玉兔精"] = ["牛魔王","铁扇公主"];console.log("k=",k,"l=",l,"m=",m);//解构赋值:声明的变量比赋值的元素少let [a1,a2] = ["语文","数学","英语"];//解构赋值元素多出的部分直接舍去console.log("a1=",a1,"a2=",a2);//解构赋值:声明的变量比赋值的元素少 //可以通过可变参数的方式将多出的部分以数组的方式赋值给最后一个元素let [b1,b2,...b3] = ["给排水","会计","计算机","土木"];console.log("b1=",b1,"b2=",b2,"b3=",b3);//通过解构赋值的方式交换两个变量的值let num1 = 10;let num2 = 20;[num1,num2] = [num2,num1];console.log("num1=",num1,"num2=",num2);</script>
</head>
<body></body>
</html>

在这里插入图片描述

⑵ 对象的解构

1) 对象的解构赋值
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>/*解构赋值*/const obj = {name:"张三",age:19,sex:"男"};//声明变量同时解构赋值,在不起别名的情况下要赋值的变量名称要和对象的属性一致let {name,age,sex} = obj;console.log("name=",name,"age=",age,"sex=",sex);//先声明变量后解构赋值const object = {role:"管理员",address:"北京市",gender:"女"};let role,address,gender;//因为在js中以 { 开始的代码默认为代码块,不会识别为对象,所以得用()括起来({role,address,gender} = object);console.log("role=",role,"address=",address,"gender=",gender);//解构赋值的对象中没有的属性,默认赋值为undefinedlet {id} = obj;console.log("id=",id);//如果声明的对象和解构对象的属性名称不一致,可以通过起别名的形式赋值let a,b,c,d;({class:a,grade:b,subject:c,teacher:d="李老师"} = {class:"一班",grade:99,subject:"语文"})console.log("a=",a,"b=",b,"c=",c,"d=",d);</script>
</head>
<body></body>
</html>

在这里插入图片描述

⑶ 对象的序列化,内嵌对象JSON

1) 通过内嵌对象JSON将对象进行序列化

对象的序列化
● JS中的对象使用时都是存在于计算机的内存中的
● 序列化指将对象转换为一个可以存储的格式
在JS中对象的序列化通常是将一个对象转换为字符串(JSON字符串)
序列化的用途(对象转换为字符串有什么用):
 ○ 对象转换为字符串后,可以将字符串在不同的语言之间进行传递,甚至人可以直接对字符串进行读写操作,使得JS对象可以在不同的语言之间传递
  ○ 用途
    ■ 作为数据交换的格式
    ■ 用来编写配置文件
如何进行序列化:
  ○ 在JS中有一个工具类 JS0N(JavaScript 0bject Notation) JS对象表示法
  ○ JS对象序列化后会变成一个字符串,这个字符串我们称其为JSON字符串
● 也可以手动的编写JSON字符串,在很多程序的配置文件就是使用JSON编写的

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>/*对象的序列化● JS中的对象使用时都是存在于计算机的内存中的● 序列化指将对象转换为一个可以存储的格式在JS中对象的序列化通常是将一个对象转换为字符串(JSON字符串)● 序列化的用途(对象转换为字符串有什么用):○ 对象转换为字符串后,可以将字符串在不同的语言之间进行传递,甚至人可以直接对字符串进行读写操作,使得JS对象可以在不同的语言之间传递○ 用途:■ 作为数据交换的格式■ 用来编写配置文件● 如何进行序列化:○ 在JS中有一个工具类 JS0N(JavaScript 0bject Notation) JS对象表示法○ JS对象序列化后会变成一个字符串,这个字符串我们称其为JSON字符串● 也可以手动的编写JSON字符串,在很多程序的配置文件就是使用JSON编写的*/const obj = {name:"张三",age:19,sex:"男"};console.log("obj对象序列化前:",typeof obj,obj);//将对象obj转换为JSON字符串const str = JSON.stringify(obj);//JSON.stringify()可以将一个对象转换成JSON字符串console.log("obj对象序列化后" ,typeof str,str);//将JSON字符串转换成对象objconst object = JSON.parse(str);//JSON.parse() 可以将一个JSON格式的字符串转换成JS对象console.log("JSON格式的字符串转换成JS对象",typeof object,object);//也可以手动的编写JSON字符串,在很多程序的配置文件就是使用JSON编写的, JSON字符串的属性名必须使用双引号引起来const jsonStr = '{"name":"李四"}';const objStr = JSON.parse(jsonStr);console.log(typeof objStr,objStr);const jsonArr = '["张三","王五"]';const objArr = JSON.parse(jsonArr);console.log(typeof objArr,objArr);console.log(objArr[0]);</script>
</head>
<body></body>
</html>

在这里插入图片描述

编写JSON的注意事项:

  1. JSON字符串有两种类型:
     JSON对象 {}
     JSON数组[]
  2. JSON字符串的属性名必须使用双引号引起来
  3. JSON中可以使用的属性值(元素)
    ● 数字(Number)
    ● 字符串(String) 必须使用双引号
    ● 布尔值(Boolean)
    ● 空值(Null)
    ● 对象(0bject {})
    ● 数组(Array[])
  4. JSON的格式和JS对象的格式基本上一致的
    注意:JSON字符串如果属性是最后一个,则不要再加
2) 通过内嵌对象JSON进行对象深复制
① 对象深复制和浅复制回顾
  • 对象浅复制

    <!DOCTYPE html>
    <html lang="en">
    <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>const obj = {name:"孙悟空",friend:{name:"牛魔王"}};//对obj进行浅复制const obj2 = Object.assign({},obj);</script>
    </head>
    <body></body>
    </html>
    

    在这里插入图片描述

  • 对象的深复制

    <!DOCTYPE html>
    <html lang="en">
    <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>const obj = {name:"孙悟空",friend:{name:"牛魔王"}};//对obj进行深复制const obj2 = structuredClone(obj);</script>
    </head>
    <body></body>
    </html>
    

    在这里插入图片描述

② 利用JSON实现对象的深复制
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>const obj = {name:"孙悟空",friend:{name:"牛魔王"}};//利用JSON实现对象的深复制const obj2 = JSON.parse(JSON.stringify(obj));</script>
</head>
<body></body>
</html>

在这里插入图片描述

⑷ 内嵌对象Map

● Map用来存储键值对结构的数据(key-value)
● 0bject中存储的数据就可以认为是一种键值对结构
Map和Obiect的主要区别:
 ○ 0bject中的属性名只能是字符串或符号,如果传递了一个其他类型的属性名,JS解释器会自动将其转换为字符串
 ○ Map中任何类型的值都可以称为数据的key

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>const  obj2 = {};const obj = {name:"孙悟空",'age':18,[Symbol()]:"哈哈",[obj2]:"嘻嘻"//obj2对象类型最终会转换成字符串类型};console.log(obj);</script>
</head>
<body></body>
</html>

在这里插入图片描述

Map的属性和方法

map.size获取map中键值对的数量
map.set(key,value)向map中添加键值对
map.get(key)根据key获取值
map.delete(key)删除指定数据
map.has(key)检查map中是否包含指定键
map.clear()删除全部的键值对

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>/*Map中任何类型的值都可以称为数据的keyMap的方法map.size()获取map中键值对的数量map.set(key,value)向map中添加键值对map.get(key)根据key获取值map.delete(key)删除指定数据map.has(key)检查map中是否包含指定键map.clear()删除全部的键值对*///创建一个Map对象obj2 = {};const  map = new Map();map.set("name","孙悟空");map.set(NaN,"不是个数字");map.set(obj2,"不是个数字");console.log(map);</script>
</head>
<body></body>
</html>

在这里插入图片描述

Map与数组的转换
 ○ Array.from(map)
 ○ [...map]
手写Map
map可以看成两个数组
const map2 = new Map([
    [“name”,“猪八戒”],
   [“age”,18],
   [{},()=>{}]
]);
遍历map
 ○ 方式一:通过普通循环和解构赋值实现map的遍历
 ○ 方式二:通过forEach遍历map
获取所有的key值
map.keys()
获取所有的value值
map.values()

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>const  map = new Map();map.set("name","孙悟空");map.set({},"哈哈");map.set("age",19);console.log(map);//Map转换成数组const arr = Array.from(map);// [['name', '孙悟空'],[{}, '哈哈'],['age', 19]]const arr2 = [...map];//手写Mapconst map2 = new Map([["name","猪八戒"],["age",18],[{},()=>{}]]);console.log(map2);//遍历map//方式一:通过普通循环和解构赋值实现map的遍历console.log("map2值为",map2);for(const [key,value] of map2){console.log("key值",key,"value值",value);}console.log("----------------------------------------------------------------------");//方式二:通过forEach遍历mapmap.forEach((value,key,map)=>{console.log("map值为",map);console.log("key值",key,"value值",value);});//返回一个新的包含 [key,value] 的 Iterator 对象,返回的迭代器的迭代顺序与 Map 对象的插入顺序相同const map3 = map.entries();console.log(map3);//获取所有的key值console.log(map.keys());//获取所有的value值console.log(map.values());</script>
</head>
<body></body>
</html>

在这里插入图片描述

⑸ 内嵌对象Set

Set用来创建一个集合,它的作用和数组类似,不同点在于Set中不能存储重复的数据
● 使用方式
  ○ 创建方式:
    ■ new Set();
    ■ new Set([...]);
  ○ 属性和方法
    ■ size 获取数量
    ■ add()添加元素
    ■ has()检查元素
    ■ delete()删除元素

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>//创建一个Setconst  set = new Set();//向Set中添加元素set.add(10);set.add("孙悟空");set.add(10);console.log(set);//通过Set给数组去重const arr = [1,2,2,3,3,3,4,5,5,6,7,7,7,7,8,9,9];const set2 = new Set(arr);const arr2 = Array.from(set2);console.log(arr2);//size 获取数量console.log(set.size);//has()检查元素console.log(set.has("孙悟空"));//delete()删除元素set.delete("孙悟空");console.log(set);</script>
</head>
<body></body>
</html>

在这里插入图片描述

⑹ 内嵌对象Math

Math是一个工具类,他为我们提供了数学运算相关的一些常量和方法
● 常量:
Math.PI 圆周率
● 方法:
Math.abs()求一个数的绝对值
Math.min()求多个值中的最小值
Math.max()求多个值中的最大值
Math.pow()求x的y次幂
Math.sqrt()求一个数的平方根
Math.floor()向下取整
Math.ceil()向上取整
Math.round()四舍五入取整
Math.trunc()直接去除小数位
Math.random()生成一个0-1之间的随机数

在这里插入图片描述

⑺ 内嵌对象Date

1)内嵌对象Date的介绍

在JS中所有的和时间相关的数据部由Date对象来表示

对象的方法:
getFullYear()获取4位年份
getMonth()返当前日期的月份(0-11)
getDate()返回当前是几日
getDay()返回当前日期是周几(0-6) 0表示周日
. . .
getTime()返回当前目期对象的时间戳, 时间戳:自1970年1月1日0时0分0秒到当前时间所经历的毫秒数计算机底层存储时间时,使用都是时间戳
Date.now()获取当前的时间戳

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>/*getFullYear()获取4位年份getMonth()返当前日期的月份(0-11)getDate()返回当前是几日getDay()返回当前日期是周几(0-6) 0表示周日getTime()返回当前目期对象的时间戳, 时间戳:自1970年1月1日0时0分0秒到当前时间所经历的毫秒数计算机底层存储时间时,使用都是时间戳Date.now()获取当前的时间戳*///直接通过new Date()创建时间对象时,它创建的是当前的时间的对象let d = new Date();//可以在Date()的构造函数中,传递一个表示时间的字符串//字符串的格式:月/日/年 时:分:秒//年-月-日T时:分:秒let date = new Date("2019-12-23T23:23:22");//new Date(年份,月,日,时,分,秒,亳秒)let dd = new Date(2016,0,1,13,45,33);console.log(d);console.log(date);console.log(dd);</script>
</head>
<body></body>
</html>

在这里插入图片描述

2) 日期的格式化

toLocaleDateString()//将日期转换为本地的字符串
参数
● 描述语言和国家信息的字符串
 ○ zh-CN 中国大陆
 ○ zh-HK 中国香港
 ○ en-US 英国美国
● 需要一个对象作为参数,在对象中可以通过对象的属性来对日期的格式进行配置
  ○ datestyle 日期的风格
  ○ timestyle 时间的风格
   full
   long
   medium
   short
  ○ hour12 是否采用12小时值
    true
     false
  ○ weekday 星期的显示方式
     long
     short
     narrow

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>/*toLocaleDateString()//将日期转换为本地的字符串参数● 描述语言和国家信息的字符串○ zh-CN 中国大陆○ zh-HK 中国香港○ en-US 英国美国● 需要一个对象作为参数,在对象中可以通过对象的属性来对日期的格式进行配置○ datestyle 日期的风格○ timestyle 时间的风格fulllongmediumshorthour12 是否采用12小时值truefalseweekday 星期的显示方式longshortnarrow*/let date = new Date();console.log(date.toLocaleDateString());</script>
</head>
<body></body>
</html>

在这里插入图片描述

⑻ 内嵌对象—包装类

在JS中,除了直接创建原始值外,也可以创建原始值的对象

通过 new String()可以创建String类型的对象
通过 new Number()可以创建Number类型的对象
通过 new Boolean()可以创建Boolean类型的对象
. . .
但是千万不要这么做

包装类:
JS中一共有5个包装类:
String ==> 字符串包装为String对象
Number ==> 数值包装为Number对象
Boolean ==> 布尔值包装为Boolean对象
BigInt ==> 大整数包装为BigInt对象
Symbol ==> 符号包装为Symbol对象

通过包装类可以将一个原始值包装为一个对象,当我们对一个原始值调用方法或属性时,JS解释器会 临时将原始值包装为对应的对象然后调用这个对象的属性或方法。由于原始值会被临时转换为对应的对象,这就意味着对象中的方法都可以直接通过原始值来调用

⑼ 字符串中的属性和方法

1)字符串中的属性

str.length
 获取字符串的长度
str[索引]
 获取指定位置的字符
str.at()(实验方法)
 根据索引获取字符,可以接受负索引
str.charAt()
 根据索引获取字符
str.concat()
 用来连接两个或多个字符串
str.includes()
 用来检查字符串中是否包含某个内容
  有返回true
  没有返回false
str.indexOf()
str.lastIndex0f()

 查询字符串中是否包含某个内容
  有返回该内容的索引
  没有返回-1
str.startsWith()
 检查一个字符串是否以指定内容开头
str.endsWith()
 检查一个字符串是否以指定内容结尾
Strings.padStart()
Strings.padEnd()

  通过添加指定的内容,使字符串保持某个长度
str.replace()
  使用一个新字符串替换一个指定内容
str.replaceAll()
  使用一个新字符串替换所有指定内容
str.slice()
  对字符串进行切片
str.substring()
  截取字符串
str.split()
  用来将一个字符串拆分为一个数组
str.toLowerCase()
  将字符串转换为小写
str.toUpperCase()
  将字符串转换为大写
str.trim()
  去除前后空格
str.trimStart()
  去除开始空格
str.trimEnd()
   去除结束空格

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>let  str = "张三";console.log(str.length);console.log(str[1]);console.log(str.at(1));console.log(str.at(-2));console.log(str.charAt(0));let str1 = "孙悟空";let str2 = "紫霞仙子";console.log(str1.concat(str2));let str3 = "adb李四¥发啊发";console.log(str3.includes("¥"));console.log(str3.indexOf("发"));console.log(str3.indexOf("拉"));console.log(str3.lastIndexOf("发"));console.log(str3.startsWith("ad"));console.log(str3.endsWith("拉拉"));console.log(str3.padStart(20,"¥"));console.log(str3.padEnd(20,"¥"));let str4 = "哈哈哈";console.log(str4.replace("哈","呵"));console.log(str4.replaceAll("哈","呵"));let str5 = "发发afaf发发";console.log(str5.slice(1,3));let str6 = "就发发发啊发发发发广告";console.log(str6.substring(5,6));let str7 = "阿发@发官@方f@gsghsh";console.log(str7.split("@"));let str8 = "QDFDsdfaf";console.log(str8.toLocaleLowerCase());console.log(str8.toLocaleUpperCase());let str9 = "   adfsafa    总共    ";console.log(str9.trim());console.log(str9.trimStart());console.log(str9.trimEnd());</script>
</head>
<body></body>
</html>

在这里插入图片描述

⑽ 正则表达式

正则表达式用来定义一个规则,通过这个规则计算机可以检查一个字符串是否符合规则或者将字符串中符合规则的内容提取出来
正则表达式也是JS中的一个对象,所以要使用正则表达式,需要先创建正则表达式的对象
在这里插入图片描述
在这里插入图片描述

1)正则表达式中test()方法

校验是否符合正则表达式

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>let re = /a{3}/;let result = re.test("aaa");console.log(result)</script>
</head>
<body></body>
</html>

在这里插入图片描述

2)正则表达式中exec()方法

获取字符串中符合正则表达式的内容

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>let str = "abcaecadcafc";//提取出str中符合axc格式的内容//g表示全局匹配let re = /a([a-z])c/ig;let result = re.exec(str);console.log(result);while(result){console.log(result[0],result[1],result[2]);result = re.exec(str);}</script>
</head>
<body></body>
</html>

在这里插入图片描述

3)字符串的正则表达式

split()
 可以根据正则表达式来对一个字符串进行拆分
search()
 可以去搜索符合正则表达式的内容第一次在字符串中出现的位置
replace()
 根据正则表达式替换字符串中的指定内容
match()
 根据正则表达式去匹配字符串中符合要求的内容(可以设置g为全匹配
matchAll()
 根据正则表达式去匹配字符串中符合要求的内容 (必须设置g全局匹配) 它返回的是一个迭代器

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>/*split()可以根据正则表达式来对一个字符串进行拆分search()可以去搜索符合正则表达式的内容第一次在字符串中出现的位置replace()根据正则表达式替换字符串中的指定内容match()根据正则表达式去匹配字符串中符合要求的内容matchAll()根据正则表达式去匹配字符串中符合要求的内容 (必须设置g全局匹配) 它返回的是一个迭代器*/let str = "a@q@faf!@";//获取字母数组console.log(str.split("@")); let str2 = "猪八戒abc沙和尚adc孙悟空";//获取中文数组console.log(str2.split(/a[bd]c/));let str3 = "dfgsg13833333333dfasg12888888888dsgsgg13455555555"//获取dfasg所在的位置console.log(str3.search("dfasg"));//查询第一个手机号所在的位置console.log(str3.search(/1[2-9]\d{9}/))//用"手机号"替换字符串中所有的手机号,正则表达式后面加个g表示全匹配let result = str3.replace(/1[2-9]\d{9}/g,"手机号");console.log(result);//获取所有的手机号组成的数组console.log(str3.match(/1[2-9]\d{9}/g))//根据正则表达式去匹配字符串中符合要求的内容 (必须设置g全局匹配) 它返回的是一个迭代器let rs = str3.matchAll(/1[2-9]\d{9}/g);for(let item of rs){console.log(item);}//根据正则表达式去匹配字符串中符合要求的内容 (必须设置g全局匹配) 它返回的是一个迭代器//可以给后九位分个组let datas = str3.matchAll(/1[2-9](\d{9})/g);for(let item of datas){console.log(item);}</script>
</head>
<body></body>
</html>

在这里插入图片描述

2. 垃圾回收机制

在这里插入图片描述

3. DOM

⑴ 为什么需要DOM

在这里插入图片描述

⑵ 什么是DOM

在这里插入图片描述

<!DOCTYPE html>
<html lang="zh">
<head><title>My Title</title>
</head>
<body><h1>A Heading</h1><a href="#">Link Text</a>
</body>
</html>

在这里插入图片描述

⑶ DOM的相相关概念

1) 节点(Node)

在这里插入图片描述

2) 关系

在这里插入图片描述

⑷ 如何使用DOM

面向对象的编程语言,无非就是两个步骤:

  1. 找对象。
  2. 搞对象。

所以使用DOM我们首先要先拿到一个DOM对象,然后以该对象为切入点来完成各种操作。

要使用DOM来操作网页,我们需要浏览器至少得先给我一个对象才能去完成各种操作
所以浏览器已经为我们提供了一个document对象,它是一个全局变量可以直接使用document代表的是整个的网页

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><button id = "btn">点我一下</button><script>/*要使用DOM来操作网页,我们需要浏览器至少得先给我一个对象才能去完成各种操作所以浏览器已经为我们提供了一个document对象,它是一个全局变量可以直接使用document代表的是整个的网页*/console.log(document);//获取button标签,并修改button中的文字//获取button对象const btn = document.getElementById("btn");console.log(btn);//修改button中的内容btn.innerText = "Click Me";</script>
</body>
</html>

在这里插入图片描述

⑸ Document对象

在这里插入图片描述

在这里插入图片描述
document对象的原型链
HTMLDocument ==> Document ==> Node ==> EventTarget ==> 0bject.prototype ==> null

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><button id = "btn">点我一下</button><a href="#"></a><script>/* document对象- document对象表示的是整个网页- document对象的原型链HTMLDocument ->Document ->Node ->EventTarget -> 0bject.prototype -> null- 凡是在原型链上存在的对象的属性和方法都可以通过Document去调用- 部分属性:document.documentElement ==> html根元素document.head ==> head元素document.title ==> title元素document.body ==> body元素document.links ==> 获取页面中所有的超链接 */console.log(document.documentElement);console.log(document.head);console.log(document.title);console.log(document.body);console.log(document.links);</script>
</body>
</html>

在这里插入图片描述

⑹ 获取元素节点Element对象

在这里插入图片描述
在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><button id = "btn">点我一下</button><a href="#"></a><span class="span">span</span><span class="span">span</span><span class="span">span</span><span class="span">span</span><form action="#" method="post"><label for="interests">选择您的兴趣:</label><br><input type="checkbox" id="sports" name="interests" value="sports"><label for="sports">运动</label><br><input type="checkbox" id="music" name="interests" value="music"><label for="music">音乐</label><br><input type="checkbox" id="books" name="interests" value="books"><label for="books">书籍</label><br><input type="checkbox" id="movies" name="interests" value="movies"><label for="movies">电影</label><br><input type="submit" value="提交"></form><script>/*● document.documentElement 获取html根元素● document.body 获取body元素● document.getElementByID() 根据id获取一个元素节点对象● document.getElementsByClassName() 根据class属性获取一组元素节点对象(实时更新列表)返回的是一个类数组对象实时更新:该方法返回的结果是一个实时更新的集合,当网页中新添加元素时,集合也会实时的刷新● document.getElementsByTagName() 根据标签名获取一组元素节点对象(实时更新列表)document.getElementsByTagName("*") 可以获取页面中所有的元素● document.getElementsByName() 根据name属性获取一组元素节点对象(实时更新列表)主要用于表单● document.querySelector() 根据选择器获取一个元素● document.querySelectorAll() 根据选择器获取一组元素,该组元素类似于数组,但数组中的一些属性无法使用*//*● document.documentElement 获取html根元素*/console.log(document.documentElement);/*● document.body 获取body元素*/console.log(document.body);/*● document.getElementByID() 根据id获取一个元素节点对象*/console.log(document.getElementById("btn"));/*● document.getElementsByClassName() 根据class属性获取一组元素节点对象(实时更新列表)返回的是一个类数组对象实时更新:该方法返回的结果是一个实时更新的集合,当网页中新添加元素时,集合也会实时的刷新*/console.log(document.getElementsByClassName("span"));/*● document.getElementsByTagName() 根据标签名获取一组元素节点对象(实时更新列表)document.getElementsByTagName("*") 可以获取页面中所有的元素*/console.log(document.getElementsByTagName("button"));console.log(document.getElementsByTagName("*"));/*● document.getElementsByName() 根据name属性获取一组元素节点对象(实时更新列表)主要用于表单*/console.log(document.getElementsByName("interests"));/*● document.querySelector() 根据选择器获取一个元素*/console.log(document.querySelector(".span"));/*● document.querySelectorAll() 根据选择器获取一组元素,该组元素类似于数组,但数组中的一些属性无法使用*/console.log(document.querySelectorAll(".span"));</script>
</body>
</html>

在这里插入图片描述
通过其他元素获取已有的Element对象:
div元素的原型链

HTMLDivElement ==> HTMLElement ==> Element ==> Node ==> EventTarget ==> 0bject.prototype ==> null

通过元素节点对象获取其他节点的方法
element.childNodes 获取当前元素的子节点(会包含空白的子节点)
element.children 获取当前元素的子元素
element.firstElementChild 获取当前元素的第一个子元素
element.lastElementChild 获取当前元素的最后一个子元素
element.nextElementSibling 获取当前元素的下一个兄弟元素
element.previousElementSibling 获取当前元素的前一个兄弟元素
element.parentNode 获取当前元素的父节点
relement.tagName 获取当前元素的标签名

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><span id="hhh"></span><div id="box1">我是box1<span class="s1"><span>我是s1</span></span><span class="s1">我是s1</span><div></div></div><span class="s1">我是s1</span><script>/*● element.childNodes 获取当前元素的子节点(会包含空白的子节点)● element.children 获取当前元素的子元素(不包含空白的子节点)● element.firstElementChild 获取当前元素的第一个子元素● element.lastElementChild 获取当前元素的最后一个子元素● element.nextElementSibling 获取当前元素的下一个兄弟元素● element.previousElementSibling 获取当前元素的前一个兄弟元素● element.parentNode 获取当前元素的父节点● element.tagName 获取当前元素的标签名*///获取div元素节点const box1 = document.getElementById("box1");//通过box1节点获取其他节点(只能获取box1的后代节点)console.log(box1.getElementsByTagName("span"));//element.childNodes 获取当前元素的子节点(会包含空白的子节点)console.log(box1.childNodes);//element.children 获取当前元素的子元素(不包含空白的子节点)console.log(box1.children);//element.firstElementChild 获取当前元素的第一个子元素console.log(box1.firstElementChild);//element.lastElementChild 获取当前元素的最后一个子元素console.log(box1.lastElementChild);//获取当前元素的下一个兄弟元素console.log(box1.previousElementSibling);//element.parentNode 获取当前元素的父节点console.log(box1.parentNode);//relement.tagName 获取当前元素的标签名console.log(box1.tagName);</script>
</body>
</html>

在这里插入图片描述
创建Element对象:

document.createElement() 根据标签名创建元素节点对象

⑺ 网页中的文本节点对象Text

在DOM中,网页中所有的文本内容都是文本节点对象(Text),可以通过获取文本对象然后完成对它的各种操作,但这种做法会使得事情变得复杂,并不建议这么做。在大部分场景下,可以通过元素的属性来操作其中的文本内容,修改文本的三个属性
element.textContent获取或修改元素中的文本内容
   获取的是标签中的内容,不会考虑css样式
element.innerText 获取或修改元素中的文本内容
    innerText获取内容时,会考虑css样式
    通过innerText去读取CSS样式,会触发网页的重排(计算CSS样式)
    当字符串中有标签时,会自动对标签进行转义
      <li> ==> glt;ligt;
element.innerHTML 获取或修改元素中的html代码
   可以直接向元素中添加html代码
    innerHTML插入内容时,有被xss注入的风险

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><div id="box"><span style="text-transform: uppercase;"><li>我是span</li></span></div><script>/*● element.textContent获取或修改元素中的文本内容获取的是标签中的内容,不会考虑css样式● element.innerText 获取或修改元素中的文本内容innerText获取内容时,会考虑css样式通过innerText去读取CSS样式,会触发网页的重排(计算CSS样式)当字符串中有标签时,会自动对标签进行转义<li> ==> glt;ligt;● element.innerHTML 获取或修改元素中的html代码可以直接向元素中添加html代码innerHTML插入内容时,有被xss注入的风险*/const box = document.getElementById("box");/*lement.textContent获取或修改元素中的文本内容获取的是标签中的内容,不会考虑css样式*/console.log(box.textContent);/*element.innerText 获取或修改元素中的文本内容innerText获取内容时,会考虑css样式通过innerText去读取CSS样式,会触发网页的重排(计算CSS样式)当字符串中有标签时,会自动对标签进行转义<li> ==> glt;ligt;*/console.log(box.innerText);/*element.innerHTML 获取或修改元素中的html代码可以直接向元素中添加html代码innerHTML插入内容时,有被xss注入的风险*/console.log(box.innerHTML);</script>
</body>
</html>

在这里插入图片描述

⑻ 属性节点(Attr)

在DOM也是一个对象,通常不需要获取对象而是直接通过元素即可完成对其的各种操作
如何操作属性节点:
方式一:
 ● 读取:元素.属性名(注意,class属性需要使用className来读取)
    读取一个布尔值时,会返回true或false
 ● 修改:元素.属性名=属性值
② 方式二:
  ● 读取:元素.getAttribute(属性名)
  ● 修改:元素.setAttribute(属性名,属性值)
  ● 删除:元素.removeAttribute(属性名)

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><div id="box"><input disabled name="userName" value="哈哈哈" type="text"></input></div><input id="inputId" disabled="disabled" name="userName" type="text" value="呵呵呵"></input><script>/*① 方式一:● 读取:元素.属性名(注意,class属性需要使用className来读取)读取一个布尔值时,会返回true或false● 修改:元素.属性名=属性值② 方式二:● 读取:元素.getAttribute(属性名)● 修改:元素.setAttribute(属性名,属性值)● 删除:元素.removeAttribute(属性名)*/const input  = document.querySelector("[name=userName]");/*① 方式一:● 读取:元素.属性名(注意,class属性需要使用className来读取)读取一个布尔值时,会返回true或false● 修改:元素.属性名=属性值*/console.log(input.type);console.log(input.disabled);input.value = "请输入姓名";input.disabled = false;/*② 方式二:● 读取:元素.getAttribute(属性名)● 修改:元素.setAttribute(属性名,属性值)● 删除:元素.removeAttribute(属性名)*/const element =  document.getElementById("inputId");console.log(element.getAttribute("type"));console.log(element.getAttribute("disabled"));//element.setAttribute("disabled",false);element.removeAttribute("disabled");element.setAttribute("value","设置value的值");</script>
</body>
</html>

在这里插入图片描述

⑼ 事件(event)提前介绍

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><!--直接在元素的属性上设置--><button onclick="alert('点击了一下')">点我一下</button><button id="btn">再点我一下</button><button id="Bt">请再点我一下</button><script>//可以通过为元素的指定属性设置回调函数的形式来绑定事件(一个事件只能绑定一个响应函数)//获取按钮对象const button = document.getElementById("btn");button.ondblclick = function(){alert("再点我一下~");}//获取按钮对象const Bt = document.getElementById("Bt");//可以通过元素addEventListener()方法来绑定事件Bt.addEventListener("click",function(){alert("通过监听绑定的点击事件1~");});Bt.addEventListener("click",function(){alert("通过监听绑定的点击事件2~");});Bt.addEventListener("click",function(){alert("通过监听绑定的点击事件3~");});</script>
</body>
</html>

在这里插入图片描述

⑽ 网页文档的加载

网页是自上向下加载的,如果将js代码编写到网页的上边,js代码在执行时,网页还没有加载完毕,这时会出现无法获取到D0M对象的情况

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>const btn = document.getElementById("btn");alert(btn);</script>
</head>
<body><button id="btn">点我一下</button>
</body>
</html>

在这里插入图片描述

无法拿到button对象

window.onload 事件会在窗口中的内容加载完毕之后才触发
documentDOMContentLoaded事件会在当前文档加载完毕之后触发

解决js代码无法获取到DOM对象的方法:

  1. 将script标签编写到body的最后
  2. 将代码编写到window.onload的回调函数中
  3. 将代码编写到document对象的DOMContentLoaded的同调函数中(执行时机更早)
  4. 将代码编写到外部的js文件中,然后以defer的形式进行引入(执行时机更早,早于D0MContentLoaded)。
1)将script标签编写到body的最后
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><button id="btn">点我一下</button><script>const btn = document.getElementById("btn");alert(btn);</script>
</body>
</html>

在这里插入图片描述

2)将代码编写到window.onload的回调函数中
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>window.onload = function(){const btn = document.getElementById("btn");alert(btn);}</script>
</head>
<body><button id="btn">点我一下</button>
</body>
</html>

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>window.addEventListener("load",function(){const btn = document.getElementById("btn");alert(btn);})</script>
</head>
<body><button id="btn">点我一下</button>
</body>
</html>

在这里插入图片描述

3)将代码编写到document对象的DOMContentLoaded的同调函数中(执行时机更早)
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>window.addEventListener("DOMContentLoaded",function(){const btn = document.getElementById("btn");alert(btn);})</script>
</head>
<body><button id="btn">点我一下</button>
</body>
</html>

在这里插入图片描述

4)将代码编写到外部的js文件中,然后以defer的形式进行引入(执行时机更早,早于D0MContentLoaded)

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>window.addEventListener("DOMContentLoaded",function(){const btn = document.getElementById("btn");alert("DOMContentLoaded中的"+btn);})</script><script defer src="./js/script.js"></script>
</head>
<body><button id="btn">点我一下</button>
</body>
</html>
const btn = document.getElementById("btn");
alert("外部js获取的"+btn);

在这里插入图片描述

⑾ DOM中元素的修改

1) DOM元素中插入新的元素

元素.appendChild 用于给一个节点添加子节点

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><button id="btn">按钮</button><hr/><ul id="list"><li id="swk">孙悟空</li><li id="ts">唐僧</li><li id="zbj">猪八戒</li></ul><script>//点击按钮,向ul列表中添加一个白龙马//获取ul标签const list = document.getElementById("list");//获取按钮const btn = document.getElementById("btn");btn.onclick = function(){//创建一个li标签const li = document.createElement("li");//向li标签中添加文本li.textContent = "白龙马";//给li添加id属性li.id = "blm";console.log(li);//将创建好的li标签添加到ul标签里//appendChild 用于给一个节点添加子节点list.appendChild(li);}</script>
</body>
</html>

在这里插入图片描述
元素.insertAdjacentElement(位置参数,节点) 可以向元素的任意位置添加元素
位置参数值:
  ○ beforeend 标签的最后添加子节点
  ○ afterbegin 标签的开始添加子节点
  ○ afterend 在元素后面插入元素(兄弟元素)
  ○ beforebegin 在元素前面插入元素(兄弟元素)

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><button id="btn">按钮</button><hr/><ul id="list"><li id="swk">孙悟空</li><li id="ts">唐僧</li><li id="zbj">猪八戒</li></ul><script>//点击按钮,向ul列表中添加一个白龙马//获取ul标签const list = document.getElementById("list");//获取按钮const btn = document.getElementById("btn");btn.onclick = function(){//创建一个li标签const li = document.createElement("li");//向li标签中添加文本li.textContent = "白龙马";//给li添加id属性li.id = "blm";console.log(li);//将创建好的li标签添加到ul标签里/*insertAdjacentElement(添加的位置,添加的元素)可以向元素的任意位置添加元素添加的位置参数:● beforeend 标签的最后添加子节点  ● afterbegin 标签的开始添加子节点● afterend 在元素后面插入元素(兄弟元素)● beforebegin 在元素前面插入元素(兄弟元素)*/list.insertAdjacentElement("beforeend",li);}</script>
</body>
</html>

在这里插入图片描述
元素.insertAdjacentHTML(位置参数,html代码) 可以向元素的任意位置添加html文本
位置参数值:
  ○ beforeend 标签的最后添加子节点
  ○ afterbegin 标签的开始添加子节点
  ○ afterend 在元素后面插入元素(兄弟元素)
  ○ beforebegin 在元素前面插入元素(兄弟元素)

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><button id="btn">按钮</button><hr/><ul id="list"><li id="swk">孙悟空</li><li id="ts">唐僧</li><li id="zbj">猪八戒</li></ul><script>//点击按钮,向ul列表中添加一个白龙马//获取ul标签const list = document.getElementById("list");//获取按钮const btn = document.getElementById("btn");btn.onclick = function(){/*元素.insertAdjacentHTML(位置参数,html代码) 可以向元素的任意位置添加html文本位置参数值:○ beforeend 标签的最后添加子节点○ afterbegin 标签的开始添加子节点○ afterend 在元素后面插入元素(兄弟元素)○ beforebegin 在元素前面插入元素(兄弟元素)*/list.insertAdjacentHTML("beforeend","<li id='blm'>白龙马</li>");}</script>
</body>
</html>

在这里插入图片描述

2) DOM中元素的替换

元素1.replaceWith(元素2) 用元素2去替换元素1

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><button id="btn">按钮</button><hr/><ul id="list"><li id="swk">孙悟空</li><li id="ts">唐僧</li><li id="zbj">猪八戒</li></ul><script>//点击按钮,替换ul列表中的孙悟空//获取按钮const btn = document.getElementById("btn");btn.onclick = function(){//创建一个li标签const li = document.createElement("li");//向li标签中添加文本li.textContent = "白龙马";//给li添加id属性li.id = "blm";console.log(li);//获取孙悟空的li标签const swk = document.getElementById("swk");//替换孙悟空的li标签swk.replaceWith(li);}</script>
</body>
</html>

在这里插入图片描述

3) DOM中元素的删除

元素.remove() 删除元素

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><button id="btn">按钮</button><hr/><ul id="list"><li id="swk">孙悟空</li><li id="ts">唐僧</li><li id="zbj">猪八戒</li></ul><script>//点击按钮,删除ul列表中的孙悟空//获取按钮const btn = document.getElementById("btn");btn.onclick = function(){//获取id为swk的liconst swk =  document.getElementById("swk");swk.remove();}</script>
</body>
</html>

在这里插入图片描述

⑿ 节点的复制

cloneNode() 方法对节点进行复制时,它会复制节点的所有特点包括各种属性。这个方法默认只会复制当前节点,而不会复制节点的子节点。可以传递一个true作为参数,这样该方法也会将元素的子节点一起复制

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><button id="btn">按钮</button><hr/><ul id="list"><li id="swk">孙悟空</li><li id="ts">唐僧</li><li id="zbj">猪八戒</li></ul><ul id="list2"> <li>蜘蛛精</li></ul><script>//点击按钮,将孙悟空复制到list2中//获取id为swk的liconst swk = document.getElementById("swk");//获取list2const list2 = document.getElementById("list2");//获取按钮const btn = document.getElementById("btn");btn.onclick = function(){//将节点swk进行复制const newli = swk.cloneNode(true);list2.appendChild(newli);}</script>
</body>
</html>

在这里插入图片描述

⒀ javascript 修改css样式

通过javascript 修改css的方式:
元素.style.样式名 = 样式值

如果样式名中含有-,则需要将样式表修改为驼峰命名法
background-color ==> backgroundColor

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>div{width: 200px;height: 200px;background-color: green;}</style>
</head>
<body><button id="btn">按钮</button><hr/><div id="dd"></div><script>//点击按钮,将div长、宽改为 400px 并且将背景颜色改成红色//获取id为dd的divconst dd = document.getElementById("dd");//获取按钮const btn = document.getElementById("btn");btn.onclick = function(){/*通过javascript 修改css的方式:元素.style.样式名 = 样式值*/dd.style.width = "400px";dd.style.height = "400px";dd.style.backgroundColor = "red";}</script>
</body>
</html>

在这里插入图片描述

⒁ javascript 获取 css样式

1) 通过 getComputedstyle() 获取样式

getComputedstyle() 它会返回一个对象,这个对象中包含了当前元素所有的生效的样式
参数:
 ○ 1.要获取样式的对象
 ○ 2.要获取的伪元素
返回值:
  返回的一个对象,对象中存储了当前元素的样式

注意:

  1. 样式对象中返回的样式值,不一定能来拿来直接计算所以使用时,一定要确保值是可以计算的才去计算
  2. 通过样式对象.样式名 只能获取样式,不能修改样式。
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>div{width: 200px;height: 200px;background-color: green;}</style>
</head>
<body><button id="btn">按钮</button><hr/><div id="dd"></div><script>//点击按钮,将div长、宽改为 400px 并且将背景颜色改成红色//获取id为dd的divconst dd = document.getElementById("dd");//获取按钮const btn = document.getElementById("btn");btn.onclick = function(){/*getComputedstyle() 它会返回一个对象,这个对象中包含了当前元素所有的生效的样式● 参数:○ 1.要获取样式的对象○ 2.要获取的伪元素● 返回值:返回的一个对象,对象中存储了当前元素的样式*/const objStyle = getComputedStyle(dd);console.log(objStyle.width);console.log(objStyle.height);console.log(parseInt(objStyle.width));console.log(objStyle.background);dd.style.width = parseInt(objStyle.width) + 100 + "px";dd.style.height = parseInt(objStyle.height) + 100 + "px";dd.style.background = "yellow";}</script>
</body>
</html>

在这里插入图片描述

2)通过属性读取样式

● 获取元素内部的宽度和高度(内容区context和内边距padding)
元素.clientHeight
元素.clientWidth
● 获取元素内部的宽度和高度(内容区context、内边距padding和边框border)
元素.offsetHeight
元素.offsetWidth
● 获取元素滚动区域的大小
元素.scrollHeight
元素.scrollWidth
● 获取元素的定位父元素
元素.offsetParent
  定位父元素:离当前元素最近的开启了定位的祖先元素,如果所有的元素都没有开启定位则返回body
● 获取元素相对与定位元素的偏移量
元素.offsetTop
元素.offsetLeft
● 获取或者设置元素滚动条的偏移量
元素.scrollTop
元素.scrollLeft

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>#dd{width: 200px;height: 200px;padding: 50px;margin: 50px;border: 10px red solid;background-color: green;overflow: auto;}#dd2{width: 100px;height: 600px;background-color: yellow;}</style>
</head>
<body><button id="btn">按钮</button><hr/><div id="dd" style="position: relative;"><div id="dd2"></div></div><script>const btn = document.getElementById("btn");const dd = document.getElementById("dd");btn.onclick = function(){/*获取元素内部的宽度和高度(内容区context和内边距padding)元素.clientHeight元素.clientWidth*/console.log(dd.clientHeight);/*获取元素内部的宽度和高度(内容区context、内边距padding和边框border)元素.offsetHeight元素.offsetWidth*/console.log(dd.offsetHeight);/*元素.scrollHeight元素.scrollWidth获取元素滚动区域的大小*/console.log(dd.scrollHeight);/*元素.offsetParent获取元素的定位父元素定位父元素:离当前元素最近的开启了定位的祖先元素,如果所有的元素都没有开启定位则返回body*/const dd2 = document.getElementById("dd2");console.log(dd2.offsetParent);/*获取元素相对与定位元素的偏移量元素.offsetTop元素.offsetLeft*/console.log(dd2.offsetLeft);/*获取或者设置元素滚动条的偏移量元素.scrollTop元素.scrollLeft*/console.log(dd.scrollTop);}</script>
</body>
</html>

在这里插入图片描述

⒂ javascript 操作元素class属性

除了直接修改样式外,也可以通过修改class属性来间接的修改样式通过class修改样式的好处:

  1. 可以一次性修改多个样式
  2. 对JS和CSS进行解耦
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.dd2{width: 200px;height: 200px;padding: 50px;margin: 50px;border: 10px red solid;background-color: green;overflow: auto;}.dd{width: 100px;height: 300px;background-color: yellow;}</style>
</head>
<body><button id="btn">按钮</button><hr/><div class="dd"></div><script>const btn = document.getElementById("btn");const dd = document.getElementsByClassName("dd")[0];console.log(dd);btn.onclick = function(){//除了直接修改样式外,也可以通过修改class属性来间接的修改样式dd.className += " dd2";}</script>
</body>
</html>

在这里插入图片描述

  • 元素.classList 是一个对象,对象中提供了对当前元素的类的各种操作方法
    元素.classList.add()向元素中添加一个或多个class

    <!DOCTYPE html>
    <html lang="en">
    <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.dd2{width: 200px;height: 200px;padding: 50px;margin: 50px;border: 10px red solid;background-color: green;overflow: auto;}.dd{width: 100px;height: 300px;background-color: yellow;}</style>
    </head>
    <body><button id="btn">按钮</button><hr/><div class="dd"></div><script>const btn = document.getElementById("btn");const dd = document.getElementsByClassName("dd")[0];console.log(dd);btn.onclick = function(){dd.classList.add("dd2");}</script>
    </body>
    </html>
    

    在这里插入图片描述
    元素.classList.remove()移除元素中的一个或多个class

    <!DOCTYPE html>
    <html lang="en">
    <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.dd2{width: 200px;height: 200px;padding: 50px;margin: 50px;border: 10px red solid;background-color: green;overflow: auto;}.dd{width: 100px;height: 300px;background-color: yellow;}</style>
    </head>
    <body><button id="btn">按钮</button><hr/><div class="dd dd2"></div><script>const btn = document.getElementById("btn");const dd = document.getElementsByClassName("dd")[0];console.log(dd);btn.onclick = function(){dd.classList.remove("dd2");}</script>
    </body>
    </html>
    

    在这里插入图片描述

元素.classList.toggle()切换元素中的class

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.dd2{width: 200px;height: 200px;padding: 50px;margin: 50px;border: 10px red solid;background-color: green;overflow: auto;}.dd{width: 100px;height: 300px;background-color: yellow;}</style>
</head>
<body><button id="btn">按钮</button><hr/><div class="dd"></div><script>const btn = document.getElementById("btn");const dd = document.getElementsByClassName("dd")[0];console.log(dd);btn.onclick = function(){dd.classList.toggle("dd2");}</script>
</body>
</html>

在这里插入图片描述

元素.classList.replace()替换class

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.dd2{width: 200px;height: 200px;padding: 50px;margin: 50px;border: 10px red solid;background-color: green;overflow: auto;}.dd{width: 100px;height: 300px;background-color: yellow;}</style>
</head>
<body><button id="btn">按钮</button><hr/><div class="dd"></div><script>const btn = document.getElementById("btn");const dd = document.getElementsByClassName("dd")[0];console.log(dd);btn.onclick = function(){dd.classList.replace("dd","dd2");}</script>
</body>
</html>

在这里插入图片描述
元素.classList.contains()检查class

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.dd2{width: 200px;height: 200px;padding: 50px;margin: 50px;border: 10px red solid;background-color: green;overflow: auto;}.dd{width: 100px;height: 300px;background-color: yellow;}</style>
</head>
<body><button id="btn">按钮</button><hr/><div class="dd"></div><script>const btn = document.getElementById("btn");const dd = document.getElementsByClassName("dd")[0];console.log(dd);btn.onclick = function(){console.log(dd.classList.contains("dd"));}</script>
</body>
</html>

在这里插入图片描述

⒃ 事件对象(Event

事件指用户和网页之间发生的交互行为。比如点击按钮、移动鼠标、改变窗口大小、表单输入等等,用户的所有操作都可以被当成是一个事件。JS中通过为事件绑定回调函数来处理事件,绑定回调函数后,事件触发后回调函数便会执行,以此来响应用户的行为,所以事件的回调函数我们也称其为事件的响应函数。事件对象是由浏览器在事件触发时所创建的对象。这个对象中封装了事件相关的各种信息。通过事件对象可以获取到事件的详细信息,比如:鼠标的坐标、键盘的按键。.浏览器在创建事件对象后,会将事件对象作为响应函数的参数传递,所以我们可以在事件的回调函数中定义一个形参来接收事件对象。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>#div{width: 200px;height: 200px;padding: 50px;margin: 50px;border: 10px red solid;background-color: green;overflow: auto;}</style>
</head>
<body><div id="div"></div><script>const div = document.getElementById("div");//记录鼠标移动的坐标/*div.addEventListener("mousemove",function(even){div.textContemnt = even.clientX + "," + even.clientY;});*/div.addEventListener("mousemove",even=>{console.log(even.clientX,even.clientY);});</script>
</body>
</html>

在这里插入图片描述

1) 事件Event对象中的属性和方法

在DOM中存在着多种不同类型的事件对象,多种事件对象有一个共同的祖先Event
event.target 触发事件的对象
event.currentTarget 绑定事件的对象(同this)
event.stopPropagation()停止事件的传导(一般用于禁止事件冒泡)
event.preventDefault()取消默认行为

事件的冒泡(bubble)

事件的冒泡就是指事件的向上传导,当元素上的某个事件被触发后,其祖先元素上的相同事件也会同时被触发。 冒泡的存在大大的简化了代码的编写,但是在一些场景下我们并不希望冒泡存。在不希望事件冒泡时,可以通过事件对象来取消冒泡

触发事件的对象和绑定事件的对象对比
event.target 触发事件的对象

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><style>#box1{width: 500px;height: 500px;background-color: green;}#box2{width: 300px;height: 300px;background-color: yellow;}#box3{width: 200px;height: 200px;background-color: blue;}</style>
</head>
<body><div id="box1"><div id="box2"><div id="box3"></div></div></div><script>const box1 = document.getElementById("box1");const box2 = document.getElementById("box2");const box3 = document.getElementById("box3");//给box1添加点击事件box1.addEventListener("click",function(even){//event.target 触发事件的对象console.log(even.target);alert("box1被点击了");});box2.addEventListener("click",function(even){//event.target 触发事件的对象console.log(even.target);alert("box2被点击了");});box3.addEventListener("click",function(even){//event.target 触发事件的对象console.log(even.target);alert("box3被点击了");});</script>
</body>
</html>

在这里插入图片描述

因为点击box3触发的事件,所以打印的都是box3对象。

event.currentTarget 绑定事件的对象(同this)

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><style>#box1{width: 500px;height: 500px;background-color: green;}#box2{width: 300px;height: 300px;background-color: yellow;}#box3{width: 200px;height: 200px;background-color: blue;}</style>
</head>
<body><div id="box1"><div id="box2"><div id="box3"></div></div></div><script>const box1 = document.getElementById("box1");const box2 = document.getElementById("box2");const box3 = document.getElementById("box3");//给box1添加点击事件box1.addEventListener("click",function(even){//event.currentTarget 绑定事件的对象(同this)console.log(even.currentTarget);alert("box1被点击了");});box2.addEventListener("click",function(even){//event.currentTarget 绑定事件的对象(同this)console.log(even.currentTarget)alert("box2被点击了");});box3.addEventListener("click",function(even){//event.currentTarget 绑定事件的对象(同this)console.log(even.currentTarget)alert("box3被点击了");});</script>
</body>
</html>

在这里插入图片描述

因为点击事件都分别绑定在box1、box2和box3上,所以分别打印box1、box2和box3对象

事件冒泡演示

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><style>#box1{width: 500px;height: 500px;background-color: green;}#box2{width: 300px;height: 300px;background-color: yellow;}#box3{width: 200px;height: 200px;background-color: blue;}</style>
</head>
<body><div id="box1"><div id="box2"><div id="box3"></div></div></div><script>const box1 = document.getElementById("box1");const box2 = document.getElementById("box2");const box3 = document.getElementById("box3");//给box1添加点击事件box1.addEventListener("click",even=>{alert("box1被点击了");});box2.addEventListener("click",function(even){alert("box2被点击了");});box3.addEventListener("click",function(even){alert("box3被点击了");});</script>
</body>
</html>

在这里插入图片描述

点击box3,box2和box1绑定的事件也被出发。

事件的冒泡和元素样式无关,只跟元素的结构有关

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><style>#box1{width: 200px;height: 200px;background-color: yellow;}#box2{width: 100px;height: 100px;background-color: rebeccapurple;position: absolute;bottom: 0;}</style>
</head>
<body><div id="box1" onclick="alert('1')"><div id="box2" onclick="alert('2')"></div></div>
</body>
</html>

在这里插入图片描述

虽然样式上box1没有包含box2,但是结构上box1还是包含了box2。触发box2的点击事件依然会触发box1的点击事件。说明事件的冒泡和元素样式无关,只跟元素的结构有关。

通过event.stopPropagation()禁用冒泡演示

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title><style>#box1{width: 500px;height: 500px;background-color: green;}#box2{width: 300px;height: 300px;background-color: yellow;}#box3{width: 200px;height: 200px;background-color: blue;}</style>
</head>
<body><div id="box1"><div id="box2"><div id="box3"></div></div></div><script>const box1 = document.getElementById("box1");const box2 = document.getElementById("box2");const box3 = document.getElementById("box3");//给box1添加点击事件box1.addEventListener("click",function(even){//通过event.stopPropagation()禁用冒泡演示alert("box1被点击了");});box2.addEventListener("click",function(even){//通过event.stopPropagation()禁用冒泡演示even.stopPropagation();alert("box2被点击了");});box3.addEventListener("click",function(even){//通过event.stopPropagation()禁用冒泡演示even.stopPropagation();alert("box3被点击了");});</script>
</body>
</html>

在这里插入图片描述

点击box3,box1和box2不会被触发

event.preventDefault()取消默认行为

演示超链接的默认行为

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title>
</head>
<body><a id="a" href="https://www.baidu.com">点我</a><script>const a = document.getElementById("a");a.addEventListener("click",function(even){alert("点击了一下");})</script>
</body>
</html>

在这里插入图片描述

给超链接绑定的点击事件执行了,但它的默认行为也执行了。

通过event.preventDefault()取消超链接默认行为

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>js讲解</title>
</head>
<body><a id="a" href="https://www.baidu.com">点我</a><script>const a = document.getElementById("a");a.addEventListener("click",function(even){even.preventDefault();alert("点击了一下");})</script>
</body>
</html>

在这里插入图片描述

给超链接绑定的点击事件执行了,但它的默认行为没有执行。

2) 事件的委派

委派就是将本该绑定给多个元素的事件,统一绑定给document,这样可以降低代码复杂度方便维护

点击按钮添加超链接演示

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><button id="btn">点击添加列表</button><ul id="list"><li><a href="javascript:;">链接一</a></li><li><a href="javascript:;">链接二</a></li><li><a href="javascript:;">链接三</a></li></ul><script>//获取ul 中所有的a标签const links = document.querySelectorAll("ul a");const btn = document.getElementById("btn");const list = document.getElementById("list");//遍历超链接,并给超链接添加点击弹出超链接文本内容的点击事件for(let i=0;i<links.length;i++){links[i].addEventListener("click",even =>{alert(even.target.textContent);});}//点击后在ul中添加一个新的libtn.addEventListener("click",even=>{list.insertAdjacentHTML("beforeend","<li><a href='javascript:;'>新的超链接</a></li>");});</script>
</body>
</html>

在这里插入图片描述

点击按钮虽然能够添加新的新的超链接,但是页面刷新就已经给所有的超链接添加了点击事件,所有后添加的列表中的超链接没有添加上点击事件

上面问题的解决思路:
我们希望: 只绑定一次事件,既可以让所有的超链接,包括当前的和未来新建的超链接都具有这些事件
思路:
可以将事件统一绑定给document,这样点击超链接时由于事件的冒泡,会导致document上的点击事件被触发,这样只绑定一次,所有的超链接都会具有这些事件

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><button id="btn">点击添加列表</button><ul id="list"><li><a href="javascript:;">链接一</a></li><li><a href="javascript:;">链接二</a></li><li><a href="javascript:;">链接三</a></li></ul><script>//获取ul 中所有的a标签//const links = document.querySelectorAll("ul a");const btn = document.getElementById("btn");const list = document.getElementById("list");/*遍历超链接,并给超链接添加点击提出超链接文本内容的点击事件for(let i=0;i<links.length;i++){links[i].addEventListener("click",even =>{alert(even.target.textContent);});}*/document.addEventListener("click",even=>{alert(even.target.textContent);});//点击后在ul中添加一个新的libtn.addEventListener("click",even=>{list.insertAdjacentHTML("beforeend","<li><a href='javascript:;'>新的超链接</a></li>");});</script>
</body>
</html>

在这里插入图片描述

虽然实现了点击新加的超链接也能弹出超链接的内容,但是鼠标点击哪里都会弹出其中的文本内容,显示这样是不合理的

上诉问题可以通过判断条件让只有点击标签a的超链接才能触发弹窗事件

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><button id="btn">点击添加列表</button><ul id="list"><li><a href="javascript:;">链接一</a></li><li><a href="javascript:;">链接二</a></li><li><a href="javascript:;">链接三</a></li></ul><script>const btn = document.getElementById("btn");const list = document.getElementById("list");//获取list中的所有超链接const links = list.getElementsByTagName("a");document.addEventListener("click",even=>{//在执行代码前先判断一下事件是谁触发的/*因为通过元素.getElementsByTagName()获取到的“集合”是伪数组所以要先转换为数组才能使用数组中的方法*///方式一:通过Array.from()方式转换成数组//const arr = Array.from(liks);//方式二:通过展开的方式转换成数组const arr = [...links];//检查even.target是否在links中存在if(arr.includes(event.target)){alert(even.target.textContent);}});//点击后在ul中添加一个新的libtn.addEventListener("click",even=>{list.insertAdjacentHTML("beforeend","<li><a href='javascript:;'>新的超链接</a></li>");});</script>
</body>
</html>

在这里插入图片描述

成功解决上诉问题

3) 事件的捕获

事件的传播机制:
在DOM中,事件的传播可以分为三个阶段:
1.捕获阶段(由祖先元素向目标元素进行事件的捕获)(默认情况下,事件不会在捕获阶段触发)
2.目标阶段(触发事件的对象)
3.冒泡阶段(由目标元素向祖先元素进行事件的冒泡)
事件的捕获,指事件从外向内的传导
当前元素触发事件以后,会先从当前元素最大的祖先元素开始向当前元素进行事件的捕获
如果希望在捕获阶段触发事件,可以将addEventListener的第三个参数设置为true般情况下我们不希望事件在捕获阶段触发,所有通常都不需要设置第三个参数

even.eventPhase 获取事件触发的阶段
1 捕获阶段 2 目标阶段 3 冒泡阶段

默认事件触发情况演示

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>#box1{width: 300px;height: 300px;background-color: red;}#box2{width: 200px;height: 200px;background-color: yellow;}#box3{width: 100px;height: 100px;background-color: green;}</style>
</head>
<body><div id="box1"><div id="box2"><div id="box3"></div></div></div><script>const box1 = document.getElementById("box1");const box2 = document.getElementById("box2");const box3 = document.getElementById("box3");box1.addEventListener("click",even=>{//eventPhase 表示事件触发的阶段,1 捕获阶段 2 目标阶段 3 冒泡阶段alert("1"+even.eventPhase);});box2.addEventListener("click",even=>{//eventPhase 表示事件触发的阶段,1 捕获阶段 2 目标阶段 3 冒泡阶段alert("2"+even.eventPhase);});box3.addEventListener("click",even=>{//eventPhase 表示事件触发的阶段,1 捕获阶段 2 目标阶段 3 冒泡阶段alert("3"+even.eventPhase);});</script>
</body>
</html>

在这里插入图片描述

由图可知,元素从目标元素开始执行事件,最后执行的是祖先的元素。并且由even.eventPhase可知box3点击事件在目标阶段执行,box2在冒泡阶段执行,box1在冒泡阶段执行

开启捕获阶段触发事件情况演示

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>#box1{width: 300px;height: 300px;background-color: red;}#box2{width: 200px;height: 200px;background-color: yellow;}#box3{width: 100px;height: 100px;background-color: green;}</style>
</head>
<body><div id="box1"><div id="box2"><div id="box3"></div></div></div><script>const box1 = document.getElementById("box1");const box2 = document.getElementById("box2");const box3 = document.getElementById("box3");box1.addEventListener("click",even=>{//eventPhase 表示事件触发的阶段,1 捕获阶段 2 目标阶段 3 冒泡阶段alert("1"+even.eventPhase);},true);box2.addEventListener("click",even=>{//eventPhase 表示事件触发的阶段,1 捕获阶段 2 目标阶段 3 冒泡阶段alert("2"+even.eventPhase);},true);box3.addEventListener("click",even=>{//eventPhase 表示事件触发的阶段,1 捕获阶段 2 目标阶段 3 冒泡阶段alert("3"+even.eventPhase);},true);</script>
</body>
</html>

在这里插入图片描述

由图可知,元素从祖先元素开始执行事件,最后执行的是目标的元素。并且由even.eventPhase可知box1点击事件在捕获阶段,box2点击事件在捕获阶段,box3在目标阶段执行

4. BOM(Browser Object Model) 浏览器对象模型

浏览器对象模型,BOM为我们提供了一组对象,通过这组对象可以完成对浏览器的各种操作。BOM对象:
Window 代表浏览器窗口(全局对象)
Navigator浏览器的对象(可以用来识别浏览器)
Location 浏览器的地址栏信息
History 浏览器的历史记录(控制浏览器前进后退)
Screen 屏幕的信息
BOM对象都是作为window对象的属性保存的,所以可以直接在JS中访问这些对象

Navigator浏览器的对象(可以用来识别浏览器)

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>var sBrowser, sUsrAg = navigator.userAgent;// The order matters here, and this may report false positives for unlisted browsers.if (sUsrAg.indexOf("Firefox") > -1) {sBrowser = "Mozilla Firefox";} else if (sUsrAg.indexOf("Opera") > -1 || sUsrAg.indexOf("OPR") > -1) {sBrowser = "Opera";} else if (sUsrAg.indexOf("Trident") > -1) {sBrowser = "Microsoft Internet Explorer";} else if (sUsrAg.indexOf("Edge") > -1) {sBrowser = "Microsoft Edge";} else if (sUsrAg.indexOf("Chrome") > -1) {sBrowser = "Google Chrome or Chromium";} else if (sUsrAg.indexOf("Safari") > -1) {sBrowser = "Apple Safari";} else {sBrowser = "unknown";}alert("当前浏览器为: " + sBrowser);</script>
</head>
<body></html>

在这里插入图片描述
在这里插入图片描述

Location 浏览器的地址栏信息

location 表示的是浏览器地址栏的信息
● 可以直接将location的值修改为一个新的地址,这样会使得网页发生跳转
location.assign()跳转到一个新的地址
location.replace()跳转到一个新的地址(无法通过回退按钮回退)
location.reload()刷新页面,可以传递一个true来强制清缓存刷新
location.href 获取当前地址

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><button id="btn">点击跳转</button><script>const btn = document.getElementById("btn");/*● 可以直接将location的值修改为一个新的地址,这样会使得网页发生跳转● location.assign()跳转到一个新的地址● location.replace()跳转到一个新的地址(无法通过回退按钮回退)● location.reload()刷新页面,可以传递一个true来强制清缓存刷新● location.href 获取当前地址*/btn.addEventListener("click",()=>{//location = "https://www.baidu.com";//location.assign("https://www.baidu.com");//location.replace("https://www.baidu.com");//location.reload(true);console.log(location.href);});</script>
</head>
<body></html>

在这里插入图片描述

History 浏览器的历史记录(控制浏览器前进后退)

history.back()回退按钮
history.forward()前进按钮
history.go()可以向前跳转也可以向后跳转,正值向前跳转,负值向后跳转

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><button id="btn">点击跳转</button><script>const btn = document.getElementById("btn");/*● history.back()回退按钮● history.forward()前进按钮● history.go()可以向前跳转也可以向后跳转,正值向前跳转,负值向后跳转*/btn.addEventListener("click",()=>{history.back();//history.forward();//history.go(-1);});</script>
</head>
<body></html>

在这里插入图片描述

5. 定时器

通过定时器,可以使代码在指定时间后执行-设置定时器的方式有两种:
setTimeout()定时器
 ○ setTimeout() 设置多少时间后代码执行,只会执行一次
参数:
  1.回调函数(要执行的代码)
  2.间隔的时间(毫秒)
 ○ clearTimeout() 关闭定时器
setInterval() 定时器
 ○ setInterval()设置定时器(每间隔一段时间代码就会执行一次)
  参数:
   1.回调函数(要执行的代码)
   2.间隔的时间(亳秒)
 ○ clearInterval()关闭定时器

setTimeout()定时器 案例

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script>setTimeout(()=>{alert("执行了~");},3000);</script>
</head>
<body></html>

在这里插入图片描述

函数三秒后执行了

setInterval() 定时器 案例

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><h1 id="num"></h1><script>const numH1 = document.getElementById("num");let num = 0;//设置定时器每隔0.1秒执行一次const timer = setInterval(()=>{num++;numH1.textContent = num;if(num === 30){//如果num等于30,关闭定时器clearInterval(timer);}},100);</script>
</html>

在这里插入图片描述

6. 调用栈(call stack)的介绍

在这里插入图片描述

在这里插入图片描述

7. 消息队列的介绍

在这里插入图片描述

在这里插入图片描述

三、jQuery介绍

1. 什么是jQuery

在这里插入图片描述

2. jQuery的缺点 —— 一个过时的库

在这里插入图片描述
在这里插入图片描述

3. 引入JQuery

在这里插入图片描述

使用公共cdn比较简单,以字节跳动静态资源为例,要引入3.x版本的jQuery,只需要将如下代码粘贴到网页中即可:

<script src="https://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/jquery/3.6.0/jquery.js"></script>

或者

<script src="https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/jquery/3.6.0/jquery.min.js"></script>

完整版代码

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><!-- <script src="https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/jquery/3.6.0/jquery.min.js"></script> --><script src="https://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/jquery/3.6.0/jquery.js"></script>
</head>
<body><script>console.log($);</script>
</html>

⑵ 本地引入:

下载地址:

开发环境版:https://code.jquery.com/jquery-3.6.1.js

生产环境版:https://code.jquery.com/jquery-3.6.1.min.js

完整代码

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="./js/jquery-3.6.1.min.js"></script>
</head>
<body><script>console.log($);</script>
</html>

在这里插入图片描述
在这里插入图片描述

4. JQuery核心函数

在这里插入图片描述
jQuery.contains()
jQuery.isArray()
jQuery.isFunction()
jQuery.isNumeric()
……

另一种是将其作为函数调用,根据参数的不同可以会发挥不同的作用。
jQuery(函数)
jQuery(选择器)
jQuery(DOM对象)
jQuery(HTML代码)

注意:上述编写代码时可以使用$代替jQuery。

⑴ jQuery核心函数的功能两种作用

1) 将它作为工具类使用

在核心函数中jQuery为我们提供了多个工具方法

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="./js/jquery-3.6.1.min.js"></script>
</head>
<body><script>var a = 111;const fn = function(){};//$.isFunction()判断参数是不是方法console.log($.isFunction(a));console.log($.isFunction(fn));</script>
</html>
2) 将它作为函数使用
① 将一个函数作为$的参数

这个函数会在文档加载完毕之后执行

相当于:document.addEventListener("DOMContentLoaded", function(){})

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="./js/jquery-3.6.1.min.js"></script>
</head>
<body><script>alert("原生alert~");jQuery(alert("jQuery修改后的alert~"));</script>
</html>

在这里插入图片描述

② 将选择器字符串作为参数

jQuery自动去网页中查找元素

作用类似于 document.querySelectorAll("...")

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="./js/jquery-3.6.1.min.js"></script>
</head>
<body><button id="btn">按钮</button><script>const btn = document.getElementById("btn");alert(btn);alert($("#btn"));</script>
</html>

在这里插入图片描述

注意:
通过jQuery核心函数查询到的结果并不是原生的DOM对象,而是一个经过jQuery包装过的新的对象,这个对象我们称其为jQuery对象。jQuery对象中为我们提供了很多新的方法,方便我们做各种DOM操作。但是jQuery对象不能直接调用原生DOM对象的方法。通常我们为jQuery对象命名时,会使用$开头,加以区分

③ 将DOM对象作为参数

可以将DOM对象转换为jQuery对象,从而使用jQuery对象的方法

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="./js/jquery-3.6.1.min.js"></script>
</head>
<body><button id="btn">按钮</button><script>const btn = document.getElementById("btn");alert($(btn));alert($("#btn"));</script>
</html>

在这里插入图片描述

④ 将html代码作为参数

会根据html代码来创建元素(jQuery对象)

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="./js/jquery-3.6.1.min.js"></script>
</head>
<body><div></div><script>var $h1 = $("<h1>我是一个h1标题</h1>");$("div").append($h1);</script>
</html>

在这里插入图片描述

5. jQuery对象

jQuery对象是jQuery中定义的对象,可以将其理解为是D0M对象的升级版,在jQuery对象中为我们提供了很多jQuery对象的方法来帮助我们简化DOM操作。

⑴ jQuery对象本质上是一个DOM对象的数组(类数组)可以通过索引获取jQuery对象中的DOM对象

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="./js/jquery-3.6.1.min.js"></script>
</head>
<body><ul><li>唐僧</li><li>孙悟空</li><li>沙和尚</li></ul><script>var $li = $("li");console.log($li);alert($li.length);alert($li[0].textContent);</script>
</html>

在这里插入图片描述

⑵ 当我们修改jQuery对象时,它会自动修改jQuery中的所有元素这一特点称为jQuery的隐式迭代

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="./js/jquery-3.6.1.min.js"></script>
</head>
<body><button id="btn">按钮</button></button><ul><li id="ts">唐僧</li><li id="swk">孙悟空</li><li id="shs">沙和尚</li></ul><script>const btn = document.getElementById("btn");var $li = $("li");btn.addEventListener("click",()=>{var text = $li.text();//读取文本,返回所有标签中的文本alert(text);$li.text("啦啦啦");var $id = $li.attr("id");//读取属性时,返回第一个标签的属性alert($id);});</script>
</html>

在这里插入图片描述

⑶ 通常情况下,jQuery对象的方法的返回值依然是一个jQuery对象

通常情况下,jQuery对象的方法的返回值依然是一个jQuery对象,所以我们可以调用一个方法后继续调用其他的jQuery对象的方法。这一特性,称为jQuery对象的 链式调用

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="./js/jquery-3.6.1.min.js"></script>
</head>
<body><button id="btn">按钮</button></button><ul><li id="ts">唐僧</li><li id="swk">孙悟空</li><li id="shs">沙和尚</li></ul><script>const btn = document.getElementById("btn");var $li = $("li");btn.addEventListener("click",()=>{var result= $li.text("新文本内容");result.css("color","red");alert($li === result);});</script>
</html>

在这里插入图片描述

相关文章:

  • 【RAG检索增强生成】MaxKB:构建企业级知识库问答系统(Ollama+Qwen2)
  • 论文阅读YOLO-World: Real-Time Open-Vocabulary Object Detection
  • 快速排序c++java代码实现
  • 全网最简单的Java设计模式【三】工厂方法模式详解
  • 实现点击按钮导出页面pdf
  • Android super.img结构及解包和重新组包
  • Android Gradle开发与应用Gradle详细使用
  • STM32第十四课:低功耗模式和RTC实时时钟
  • 「C++系列」C++ 变量作用域
  • 谈谈检测浏览器类型
  • Jenkins 使用 Publish over SSH进行远程访问
  • p标签文本段落中因编辑器换行引起的空格问题完美解决方案
  • 【Element-UI】vue使用 this.$confirm区分取消与关闭,vue给this.$confirm设置多个按钮
  • WHAT - React Immer
  • QT学习(6)——QT中的定时器事件,两种实现方式;事件的分发event,事件过滤器
  • 【译】JS基础算法脚本:字符串结尾
  • canvas实际项目操作,包含:线条,圆形,扇形,图片绘制,图片圆角遮罩,矩形,弧形文字...
  • Cumulo 的 ClojureScript 模块已经成型
  • Electron入门介绍
  • ES6--对象的扩展
  • iOS筛选菜单、分段选择器、导航栏、悬浮窗、转场动画、启动视频等源码
  • k个最大的数及变种小结
  • Python学习之路13-记分
  • Zsh 开发指南(第十四篇 文件读写)
  • 闭包--闭包之tab栏切换(四)
  • 短视频宝贝=慢?阿里巴巴工程师这样秒开短视频
  • 马上搞懂 GeoJSON
  • 前端攻城师
  • 日剧·日综资源集合(建议收藏)
  • 一个完整Java Web项目背后的密码
  • 在 Chrome DevTools 中调试 JavaScript 入门
  • 【干货分享】dos命令大全
  • 1.Ext JS 建立web开发工程
  • ​【数据结构与算法】冒泡排序:简单易懂的排序算法解析
  • ​LeetCode解法汇总1410. HTML 实体解析器
  • ​软考-高级-信息系统项目管理师教程 第四版【第23章-组织通用管理-思维导图】​
  • #图像处理
  • $jQuery 重写Alert样式方法
  • (1/2)敏捷实践指南 Agile Practice Guide ([美] Project Management institute 著)
  • (4) PIVOT 和 UPIVOT 的使用
  • (delphi11最新学习资料) Object Pascal 学习笔记---第14章泛型第2节(泛型类的类构造函数)
  • (SpringBoot)第二章:Spring创建和使用
  • (vue)el-checkbox 实现展示区分 label 和 value(展示值与选中获取值需不同)
  • (vue)el-tabs选中最后一项后更新数据后无法展开
  • (一)基于IDEA的JAVA基础1
  • (原創) 如何安裝Linux版本的Quartus II? (SOC) (Quartus II) (Linux) (RedHat) (VirtualBox)
  • (转)Android中使用ormlite实现持久化(一)--HelloOrmLite
  • (转)GCC在C语言中内嵌汇编 asm __volatile__
  • (转)详解PHP处理密码的几种方式
  • (轉貼) 資訊相關科系畢業的學生,未來會是什麼樣子?(Misc)
  • .[hudsonL@cock.li].mkp勒索病毒数据怎么处理|数据解密恢复
  • .NET / MSBuild 扩展编译时什么时候用 BeforeTargets / AfterTargets 什么时候用 DependsOnTargets?
  • .NET Core MongoDB数据仓储和工作单元模式封装
  • .NET Core 将实体类转换为 SQL(ORM 映射)
  • .NET core 自定义过滤器 Filter 实现webapi RestFul 统一接口数据返回格式