权威网站: MDN

JavaScript权威网站: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript

目录

一、JavaScript基础

1.JavaScript介绍

1.1 JavaScript 是什么

1.2 JavaScript 书写位置

1.3 JavaScript 注释

1.4 JavaScript 结束符

1.5 JavaScript 输入输出语法

1.6 字面量

2.变量

2.1 变量是什么?

2.2 变量的基本使用

2.3 变量的本质

2.4 变量命名规则与规范

2.5变量拓展-let和var的区别

2.6变量拓展-数组

3.常量

4.数据类型

4.1 数据类型 – 数字类型(Number)

4.2 数据类型 – 字符串类型(string)

4.3数据类型 – 布尔类型(boolean)

4.4数据类型 – 未定义类型(undefined)

4.5数据类型 – null(空类型)

4.6控制台输出语句和检测数据类型

5.类型转换

5.1 为什么需要类型转换

5.2 隐式转换

5.3 显式转换

综合案例:用户订单信息案例

6.运算符

6.1 赋值运算符

6.2 一元运算符

6.3 比较运算符

6.4 逻辑运算符

6.5 运算符优先级

7.语句

7.1 表达式语句

7.2 分支语句( if语句、三元运算符、switch语句 )

7.3 循环结构

综合案例:简易ATM取款机案例

8.for循环

9.数组

9.1 数组是什么

9.2 数组的基本使用

9.3 操作数组

综合案例:根据数据生成柱形图

9.4 冒泡排序

9.5 数组排序

10.函数

10.1 为什么需要函数

10.2 函数使用

10.3 函数传参

10.4 函数返回值

10.5 函数细节补充

10.6 作用域

10.7 匿名函数

综合案例:转换时间案例

10.8 逻辑中断

10.对象

10.1 对象是什么

10.2 对象使用

10.2 对象使用

10.3 遍历对象

10.4 内置对象

综合案例:学成在线页面渲染案例

拓展-术语解释

拓展- 基本数据类型和引用数据类型

拓展- 变量声明

二、Web APIs

1. Web API 基本认知

1.1 作用和分类

1.2 什么是DOM

1.3 DOM树

1.4 DOM对象(重要)

2.获取DOM对象

2.1 根据CSS选择器来获取DOM元素 (重点)

2.2 其他获取DOM元素方法(了解)

3. 操作元素内容

4.操作元素属性

4.1 操作元素常用属性

4.2 操作元素样式属性

案例:轮播图随机版

4.3 操作表单元素属性

4.4 自定义属性

5.定时器-间歇函数

综合案例:轮播图定时器版

6.事件监听(绑定)

6.1 事件监听

6.2 事件监听版本

7.事件类型

案例:轮播图完整版

8.事件对象

8.1 获取事件对象

8.2 事件对象常用属性

9.环境对象

10.回调函数

综合案例:Tab栏切换

重点案例:全选文本框

11.事件流

11.1 事件流和两个阶段说明

11.2 事件捕获

11.3 事件冒泡

11.4 阻止冒泡

11.5 解绑事件

拓展:鼠标经过事件的区别、两种注册事件的区别

12.事件委托

案例:tab栏切换改造

13.其他事件

13.1 页面加载事件

13.2 页面滚动事件

13.3 页面尺寸事件

13.4 元素尺寸与位置

总结​

综合案例:电梯导航

14. 日期对象


一、JavaScript基础

1.JavaScript介绍

1.1 JavaScript 是什么 

1. JavaScript (是什么?)

是一种运行在客户端(浏览器)的编程语言,实现人机交互效果。

2. 作用(做什么?)

– 网页特效 (监听用户的一些行为让网页作出对应的反馈)

– 表单验证 (针对表单数据的合法性进行判断)

– 数据交互 (获取后台的数据, 渲染到前端)

– 服务端编程 (node.js)

3. JavaScript的组成(有什么?)

 ECMAScript: 规定了js基础语法核心知识。

比如:变量、分支语句、循环语句、对象等等

 Web APIs :

  • DOM 操作文档,比如对页面元素进行移动、大小、添加删除等操作
  • BOM 操作浏览器,比如页面弹窗,检测窗口宽度、存储数据到浏览器等等

1.2 JavaScript 书写位置

1. 内部 JavaScript 

直接写在html文件里,用script标签包住

规范:script标签写在</body>上面

<body><!-- 内部 --><script>alert('努力,奋斗');</script>
</body>

注意事项

将<script>放在HTML文件的底部附近的原因是浏览器会按照代码在文件中的顺序加载HTML。

如果先加载的JavaScript期望修改其下方 HTML,那么它可能由于HTML尚未被加载而失效。

因此,将JavaScript代码放在HTM页面的底部附近通常是最好的策略。

2. 外部 JavaScript

代码写在以.js结尾的文件里

语法:通过script标签,引入到html页面中。

<body><!-- 外部 --><script src="./js/my.js"></script>
</body>

注意事项

1. script标签中间无需写代码,否则会被忽略!

2. 外部JavaScript会使代码更加有序,更易于复用,且没有了脚本的混合,HTML也会更加易读,因此这是个好的习惯。

3. 内联 JavaScript

代码写在标签内部

语法:

<body><button onclick="alert('努力,奋斗')">点击</button>
</body>

1.3 JavaScript 注释

● 单行注释(//)

作用://右边这一行的代码会被忽略

快捷键:ctrl + /

● 块注释(/* */)

作用:在/* 和 */ 之间的所有内容都会被忽略

快捷键:shift + alt + A

1.4 JavaScript 结束符

● 结束符

作用: 使用英文的 ; 代表语句结束

实际情况: 实际开发中,可写可不写, 浏览器(JavaScript引擎)可以自动推断语句的结束位置

现状: 在实际开发中,越来越多的人主张,书写JavaScript代码时省略结束符

约定:为了风格统一,结束符要么每句都写,要么每句都不写(按照团队要求)

1.5 JavaScript 输入输出语法

输出和输入也可理解为人和计算机的交互,用户通过键盘、鼠标等向计算机输入信息,计算机处理后再展示结果给用户,这便是一次输入和输出的过程。

1.输出语法:

语法1:

作用:向body内输出内容

注意:如果输出的内容写的是标签,也会被解析成网页元素,如:

语法2:

作用:页面弹出警告对话框

语法3:

作用:控制台输出语法,程序员调试使用

2. 输入语法:

语法:

作用:显示一个对话框,对话框中包含一条文字信息,用来提示用户输入文字

3.JavaScript 代码执行顺序:

按HTML文档流顺序执行JavaScript代码

alert() 和 prompt() 它们会跳过页面渲染先被执行

1.6 字面量

在计算机科学中,字面量(literal)是在计算机中描述 事/物

比如:

我们工资是: 8000 此时8000就是数字字面量;'黑马程序员' 字符串字面量;还有接下来学的 [] 数组字面量 {} 对象字面量 等等

2.变量

2.1 变量是什么?

变量:

● 白话:变量就是一个装东西的盒子。

● 通俗:变量是计算机中用来存储数据的“容器”,它可以让计算机变得有记忆。

● 注意:变量不是数据本身,它们仅仅是一个用于存储数值的容器。可以理解为是一个个用来装东西的纸箱子。

2.2 变量的基本使用

1. 声明变量: 

要想使用变量,首先需要创建变量(也称为声明变量或者定义变量)

语法:

声明变量有两部分构成:声明关键字、变量名(标识)

let 即关键字 (let: 允许、许可、让),所谓关键字是系统提供的专门用来声明(定义)变量的词语

举例:let age

我们声明了一个age变量,age 即变量的名称,也叫标识符

2. 变量赋值:

定义了一个变量后,就能够初始化它(赋值)。在变量名之后跟上一个“=”,然后是数值。

注意:是通过变量名来获得变量里面的数据

简单点,也可以声明变量的时候直接完成赋值操作,这种操作也称为 变量初始化

3. 更新变量: 

变量赋值后,还可以通过简单地给它一个不同的值来更新它。

注意: let 不允许多次声明一个变量

4. 声明多个变量: 

变量赋值后,还可以通过简单地给它一个不同的值来更新它。

语法:多个变量中间用逗号隔开。

说明:看上去代码长度更短,但并不推荐这样。为了更好的可读性,请一行只声明一个变量。

变量案例:交换变量的值

核心思路:使用一个临时变量temp用来做中间存储。

<body><script>let num1 = 'pink老师'let num2 = '周深'let temp// 都是把右边给左边temp = num1num1 = num2num2 = tempconsole.log(num1, num2)</script>
</body>

2.3 变量的本质

内存:计算机中存储数据的地方,相当于一个空间

变量本质:是程序在内存中申请的一块用来存放数据的小空间

2.4 变量命名规则与规范

规则:必须遵守,不遵守报错 (法律层面)

规范:建议,不遵守不会报错,但不符合业内通识 (道德层面)

1. 规则:

不能用关键字。关键字:有特殊含义的字符,JavaScript内置的一些英语词汇。例如:let、var、if、for等

只能用下划线、字母、数字、$组成,且数字不能开头

字母严格区分大小写,如Age和age是不同的变量

2. 规范:

起名要有意义

遵守小驼峰命名法

第一个单词首字母小写,后面每个单词首字母大写。例:userName、myFirstName

2.5变量拓展-let和var的区别

let 和 var 区别:

在较旧的JavaScript,使用关键字 var 来声明变量 ,而不是 let。

var 现在开发中一般不再使用它,只是我们可能再老版程序中看到它。

let 为了解决 var 的一些问题。

var 声明:

○ 可以先使用 在声明 (不合理)

○ var 声明过的变量可以重复声明(不合理)

○ 比如变量提升、全局变量、没有块级作用域等等

结论:以后声明变量统一使用 let

2.6变量拓展-数组

● 数组 (Array) —— 一种将一组数据存储在单个变量名下的优雅方式

2.6.1 数组的基本使用

1. 声明语法:let 数组名 = [数据1, 数据2, ..., 数据n]

○ 数组是按顺序保存,所以每个数据都有自己的编号

○ 计算机中的编号从0开始,第二个数据编号为1,以此类推

○ 在数组中,数据的编号也叫索引或下标

○ 数组可以存储任意类型的数据

2.取值语法:数组名[下标]

通过下标取数据。取出来是什么类型的,就根据这种类型特点来访问。

3.一些术语:

● 元素:数组中保存的每个数据都叫数组元素

● 下标:数组中数据的编号

● 长度:数组中数据的个数,通过数组的length属性获得

let arr = ['刘德华', '张学友', '黎明', '郭富城', 'pink老师', 10]
console.log(arr.length)  // 6

3.常量

概念:使用 const 声明的变量称为“常量”。

使用场景:当某个变量永远不会改变的时候,就可以使用 const 来声明,而不是let。

命名规范:和变量一致

常量使用:

// 1.常量 不允许更改值const PI = 3.14console.log(PI)

注意: 常量不允许重新赋值,声明的时候必须赋值(初始化)

小技巧:不需要重新赋值的数据使用const 

const — 类似于 let ,但是变量的值无法被修改。

4.数据类型

JS 数据类型整体分为两大类:

● 基本数据类型

● 引用数据类型

4.1 数据类型 – 数字类型(Number)

即我们数学中学习到的数字,可以是整数、小数、正数、负数。

JavaScript 中的正数、负数、小数等 统一称为 数字类型。

注意事项:

JS是弱数据类型,变量属于哪种类型,只有赋值之后我们才能确认

Java是强数据类型 例如 int a = 3 必须是整数

数字可以有很多操作,比如,乘法 * 、除法 / 、加法 + 、减法 - 等等,所以经常和算术运算符一起。

数学运算符也叫算术运算符,主要包括加、减、乘、除、取余(求模)。

➱ +:求和

➱ -:求差

➱ *:求积

➱ /:求商

➱ %:取模(取余数),开发中经常作为某个数字是否被整除

同时使用多个运算符编写程序时,会按着某种顺序先后执行,我们称为优先级。

JavaScript中优先级越高越先被执行,优先级相同时以书从左向右执行。

● 总结: 先乘除取余,后加减,有小括号先算小括号里面的

NaN 代表一个计算错误。它是一个不正确的或者一个未定义的数学操作所得到的结果。

NaN 是粘性的。任何对 NaN 的操作都会返回 NaN

4.2 数据类型 – 字符串类型(string)

通过单引号( '') 、双引号( "")或反引号( ` ) 包裹的数据都叫字符串,单引号和双引号没有本质上的区别,推荐使用单引号。

注意事项:

1. 无论单引号或是双引号必须成对使用

2. 单引号/双引号可以互相嵌套,但是不以自已嵌套自已(口诀:外双内单,或者外单内双)

3. 必要时可以使用转义符 \,输出单引号或双引号

字符串拼接

场景: + 运算符 可以实现字符串的拼接。

口诀:数字相加,字符相连

    let age = 25document.write('我今年' + age + '岁了')

模板字符串

使用场景:拼接字符串和变量

在没有它之前,要拼接变量比较麻烦

语法:`` (反引号) 在英文输入模式下按键盘的tab键上方那个键(1左边那个键)。内容拼接变量时,用 ${ } 包住变量

  <script>// // 模板字符串 外面用`` 里面 ${变量名}let uname = prompt('请输入您的姓名:')let age = prompt('请输入您的年龄:')document.write(`大家好,我叫${uname}, 我今年贵庚${age}岁了`)</script>

4.3数据类型 – 布尔类型(boolean)

表示肯定或否定时在计算机中对应的是布尔类型数据。

它有两个固定的值true和false,表示肯定的数据用true(真),表示否定的数据用false(假)。

4.4数据类型 – 未定义类型(undefined)

未定义是比较特殊的类型,只有一个值undefined。

什么情况出现未定义类型?

只声明变量,不赋值的情况下,变量的默认值为undefined,一般很少直接为某个变量赋值为undefined。

    // 未定义类型   弱数据类型   声明一个变量未赋值就是 undefinedlet numconsole.log(num)

工作中的使用场景:

我们开发中经常声明一个变量,等待传送过来的数据。如果我们不知道这个数据是否传递过来,此时我们可以通过检测这个变量是不是undefined,就判断用户是否有数据传递过来。

4.5数据类型 – null(空类型)

JavaScript 中的 null 仅仅是一个代表“无”、“空”或“值未知”的特殊值

    //  null 空的let obj = nullconsole.log(obj)

null 和 undefined 区别:

● undefined 表示没有赋值

● null 表示赋值了,但是内容为空

    // 计算有区别console.log(undefined + 1)  // NaNconsole.log(null + 1) // 1

null 开发中的使用场景:

官方解释:把null作为尚未创建的对象

通俗解释:将来有个变量里面存放的是一个对象,但是对象还没创建好,可以先给个null

4.6控制台输出语句和检测数据类型

1.控制台输出语句:

控制台语句经常用于测试结果来使用。

数字型和布尔型颜色为蓝色,字符串和undefined颜色为灰色

2. 通过 typeof 关键字检测数据类型

typeof 运算符可以返回被检测的数据类型。它支持两种语法形式:

1. 作为运算符: typeof x (常用的写法)

2. 函数形式: typeof(x)

换言之,有括号和没有括号,得到的结果是一样的,所以我们直接使用运算符的写法。

 5.类型转换

5.1 为什么需要类型转换

JavaScript是弱数据类型: JavaScript也不知道变量到底属于那种数据类型,只有赋值了才清楚。

坑:使用表单、prompt 获取过来的数据默认是字符串类型的,此时不能直接进行加法运算。

此时需要转换变量的数据类型。

通俗来说,就是把一种数据类型的变量转换成我们需要的数据类型。

5.2 隐式转换

某些运算符被执行时,系统内部自动将数据类型进行转换,这种转换称为隐式转换。

规则:

1. + 号两边只要有一个是字符串,都会把另外一个转成字符串

    console.log('pink' + 1) // pink1console.log(2 + 2)   // 4console.log(2 + '2') // 22

2. 除了+以外的算术运算符 比如 - * / 等都会把数据转成数字类型

    console.log(2 - 2)    // 0console.log(2 - '2')  // 0 

缺点: 转换类型不明确,靠经验才能总结

小技巧:

1. +号作为正号解析可以转换成数字型

console.log(+'123')  // 转换为数字型 123

2.任何数据和字符串相加结果都是字符串

5.3 显式转换

编写程序时过度依靠系统内部的隐式转换是不严禁的,因为隐式转换规律并不清晰,大多是靠经验总结的规律。为了避免因隐式转换带来的问题,通常根逻辑需要对数据进行显示转换。

概念: 自己写代码告诉系统该转成什么类型

转换为数字型有三种方法:

 Number(数据)

转成数字类型

如果字符串内容里有非数字,转换失败时结果为NaN(Not a Number)即不是一个数字

NaN也是number类型的数据,代表非数字

 parseInt(数据) 只保留整数

 parseFloat(数据) 可以保留小数

转换为字符型:

 String(数据)

 变量.toString(进制)

综合案例:用户订单信息案例

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>h2 {text-align: center;}table,th,td {border: 1px solid #000;}table {/* 合并相邻边框 */border-collapse: collapse;text-align: center;height: 80px;margin: 0 auto;}th {padding: 10px 30px;}</style>
</head>
<body><h2>订单确认</h2><script>let price = +prompt('请输入商品价格:')let num = +prompt('请输入商品数量:')let address = prompt('请输入收货地址:')let total = price * numdocument.write(`<table><thead><th>商品名称</th><th>商品价格</th><th>商品数量</th><th>总价</th><th>收货地址</th></thead><tbody><tr><td>小米手机青春PLUS</td><td>${price}元</td><td>${num}</td><td>${total}元</td><td>${address}</td></tr></tbody></table>`)</script>
</body>
</html>

 6.运算符

6.1 赋值运算符

赋值运算符(=):对变量进行赋值的运算符

= 将等号右边的值赋予给左边, 要求左边必须是一个容器

其他赋值运算符: += 、-= 、*= 、/= 、%=

使用这些运算符可以在对变量赋值时进行快速操作

6.2 一元运算符

众多的JavaScript的运算符可以根据所需表达式的个数,分为一元运算符、二元运算符、三元运算符。

自增(++) 

作用:让变量的值 +1

● 自减(--)

作用:让变量的值 -1

● 使用场景:经常用于计数来使用。 比如进行10次操作,用它来计算进行了多少次了

● 自增运算符的用法:

前置自增:                                                        后置自增:

前置自增和后置自增的区别

前置自增:先自加再使用(记忆口诀:++在前 先加)

后置自增:先使用再自加(记忆口诀:++在后 后加)

注意:

1. 前置自增和后置自增独立使用时二者并没有差别!

2. 实际开发中,我们一般都是单独使用的,后置自增会使用相对较多

拓展:

输出7

6.3 比较运算符

使用场景:比较两个数据大小、是否相等

>: 左边是否大于右边

<: 左边是否小于右边

>=: 左边是否大于或等于右边

<=: 左边是否小于或等于右边

==: 左右两边是否相等

===: 左右两边是否类型都相等

!==: 左右两边是否不全等

比较运算符有隐式转换。比较结果为boolean类型,即只会得到true或false。

= 和 == 和 === 对比

● = 单等是赋值

● == 是判断

● === 是全等

开发中判断是否相等,强烈推荐使用 ===

● 字符串比较,是比较的字符对应的ASCII码

从左往右依次比较,如果第一位一样再比较第二位,以此类推

● NaN不等于任何值,包括它本身,涉及到NaN都是false

● 尽量不要比较小数,因为小数有精度问题

● 不同类型之间比较会发生隐式转换

最终把数据隐式转换转成number类型再比较

所以开发中,如果进行准确的比较我们更喜欢 === 或者 !==

6.4 逻辑运算符

表达式1 && 表达式2:表达式1为真,返回表达式2;表达式1为假,返回表达式1

表达式1  ||  表达式2:表达式1为真,返回表达式1;表达式1为假,返回表达式2

6.5 运算符优先级

一元运算符里面的逻辑非优先级很高。逻辑与比逻辑或优先级高。

7.语句

7.1 表达式语句

● 表达式:表达式是可以被求值的代码,JavaScript 引擎会将其计算出一个结果。

● 语句:语句是一段可以执行的代码。比如:prompt()可以弹出一个输入框,还有if语句、for循环语句等等

区别:

表达式:因为表达式可被求值,所以它可以写在赋值语句的右侧。如:num = 3 + 4

语句:而语句不一定有值,所以比如alert()、for和break等语句就不能被用于赋值。

7.2 分支语句( if语句、三元运算符、switch语句 )

程序三大流程控制语句

● 以前我们写的代码,写几句就从上往下执行几句,这种叫顺序结构

● 有的时候要根据条件选择执行代码,这种就叫分支结构

● 某段代码被重复执行,就叫循环结构

● 分支语句可以让我们有选择性的执行想要的代码

● 分支语句包含:if分支语句、三元运算符、switch语句

7.2.1 if语句

if语句有三种使用:单分支、双分支、多分支

● 单分支 if 语法:

括号内的条件为true时,进入大括号里执行代码;小括号内的结果若不是布尔类型时,会发生隐式转换转为布尔类型。除了0 所有的数字都为真,除了''所有的字符串都为真true

如果大括号只有一个语句,大括号可以省略,但是不提倡这么做

● 双分支 if 语法:

● 多分支 if 语法:

使用场景:适合于有多个结果的时候,比如学习成绩可以分为: 优 良 中 差

先判断条件1,若满足条件1就执行代码1,其他不执行;若不满足则向下判断条件2,满足条件2执行代码2,其他不执行;若依然不满足继续往下判断,依次类推;若以上条件都不满足,执行else里的代码n

7.2.2 三元运算符

使用场景: 其实是比if双分支更简单的写法,可以使用 三元表达式,一般用来取值

符号:? 与 : 配合使用

语法:

数字补0案例

用户输入1个数,如果数字小于10,则前面进行补0, 比如09

  <script>// 1. 用户输入 let num = prompt('请您输入一个数字:')// 2. 判断输出- 小于10才补0num = num < 10 ? 0 + num : numalert(num)</script>

7.2.3 switch语句

语法:

释义:

找到跟小括号里数据全等的case值,并执行里面对应的代码,例:数据若跟值2全等,则执行代码2;若没有全等 === 的则执行default里的代码

注意事项:

1. switch case语句一般用于等值判断,不适合于区间判断

2. switch case一般需要配合break关键字使用,没有break会造成case穿透

简单计算器案例

<script>// 1.用户输入  2个数字 +  操作符号  + - *  / let num1 = +prompt('请您输入第一个数字:')let num2 = +prompt('请您输入第二个数字:')let sp = prompt('请您输入 + - * / 其中一个:')// 2. 判断输出switch (sp) {case '+':alert(`两个数的加法操作是${num1 + num2}`)breakcase '-':alert(`两个数的减法操作是${num1 - num2}`)breakcase '*':alert(`两个数的乘法操作是${num1 * num2}`)breakcase '/':alert(`两个数的除法操作是${num1 / num2}`)breakdefault:alert(`请输入+-*/`)} </script>

7.3 循环结构

7.3.1 断点调试

作用:学习时可以帮助更好的理解代码运行,工作时可以更快找到bug

浏览器打开调试界面

1. 按F12打开开发者工具

2. 点到sources一栏

3. 选择代码文件,添加断点并刷新

断点:在某句代码上加的标记就叫断点,当程序执行到这句有标记的代码时会停下来

7.3.2 while 循环

while循环就是在满足条件期间,重复执行某些代码。

1. while 循环基本语法:

释义:

跟if语句很像,都要满足小括号里的条件为true才会进入循环体执行代码。while大括号里代码执行完毕后不会跳出,而是继续回到小括号里判断条件是否满足,若满足又执行大括号里的代码,然后再回到小括号判断条件,直到括号内条件不满足,即跳出。

2. while 循环三要素:

循环的本质就是以某个变量为起始值,然后不断产生变化量,慢慢靠近终止条件的过程。

所以,while循环需要具备三要素:

1. 变量起始值

2. 终止条件(没有终止条件,循环会一直执行,造成死循环)

3. 变量变化量(用自增或者自减)

3 循环退出

循环结束:

● break:退出循环

● continue:结束本次循环,继续下次循环

区别: 

● continue退出本次循环,一般用于排除或者跳过某一个选项的时候, 可以使用continue

● break退出整个循环,一般用于结果已经得到, 后续的循环不需要的时候可以使用

综合案例:简易ATM取款机案例

<script>// 1. 开始循环 输入框写到 循环里面// 3. 准备一个总的金额let money = 100while (true) {let re = +prompt(`请您选择操作:1.存钱2.取钱3.查看余额4.退出`)// 2. 如果用户输入的 4 则退出循环, break  写到if 里面,没有写到switch里面, 因为4需要break退出循环if (re === 4) {break}// 4. 根据输入做操作switch (re) {case 1:// 存钱let cun = +prompt('请输入存款金额')money = money + cunbreakcase 2:// 存钱let qu = +prompt('请输入取款金额')money = money - qubreakcase 3:// 存钱alert(`您的银行卡余额是${money}`)break}}</script>

8.for循环

1. for循环语法

作用:重复执行代码

好处:把声明起始值、循环条件、变化值写到一起,让人一目了然,它是最常使用的循环形式

2. 退出循环

● continue退出本次循环,一般用于排除或者跳过某一个选项的时候,可以使用continue

● break退出整个for循环,一般用于结果已经得到, 后续的循环不需要的时候可以使用

了解:

1. while(true) 来构造“无限”循环,需要使用break退出循环。

2. for(;;) 也可以来构造“无限”循环,同样需要使用break退出循环。

for循环和while循环的区别: 

● 当如果明确了循环的次数的时候推荐使用for循环

● 当不明确循环的次数的时候推荐使用while循环

3. for 循环嵌套:一个循环里再套一个循环,一般用在for循环里

案例:九九乘法表

  <script>// 1. 外层循环控制行数for (let i = 1; i <= 9; i++) {// 2. 里层循环控制列数for (let j = 1; j <= i; j++) {document.write(`<span>${j} X ${i} = ${i * j}</span>`)}// 换行document.write('<br>')}</script>

9.

9.1 数组是什么

数组:(Array)是一种可以按顺序保存数据的 数据类型
场景:如果有多个数据可以用数组保存起来,然后放到一个变量中,管理非常方便

9.2 数组的基本使用

1. 声明语法:

数组是按顺序保存,所以每个数据都有自己的编号

计算机中的编号从0开始,所以小明的编号为0,小刚编号为1,以此类推

在数组中,数据的编号也叫索引或下标

数组可以存储任意类型的数据

2. 取值语法:数组名[下标]
通过下标取数据,取出来是什么类型的,就根据这种类型特点来访问
3. 一些术语:
元素:数组中保存的每个数据都叫数组元素
下标:数组中数据的编号
长度:数组中数据的个数,通过数组的length属性获得
4. 遍历数组(重点)
用循环把数组中每个元素都访问到,一般会用for循环遍历
语法:

9.3 操作数组

数组本质是数据集合, 操作数据无非就是 增 删 改 查
语法:

 操作数组-新增

arr.push() 方法将一个或多个元素添加到数组的末尾,并返回该数组的新长度 (重点)
语法:

arr.unshift(新增的内容) 方法将一个或多个元素添加到数组的 开头 ,并返回该数组的新长度
语法:

操作数组-删除 

arr. pop() 方法从数组中删除最后一个元素,并返回该元素的值

语法:arr.pop()

arr. shift() 方法从数组中删除第一个元素,并返回该元素的值
语法:arr.shift()

数组. splice() 方法 删除指定元素

语法:数组.splice(start, deleteCount, item1, item2, ..., itemN)

从start开始删除deleteCount个数组元素,并从start处开始添加item(item可加可不加)

使用场景:
1. 随机抽奖,中奖的用户就需要从数组里面删除,不允许重复抽奖
2. 点击删除按钮,相关的数据会从商品数据中删除

语法:

解释:
start 起始位置: 指定修改的开始位置(从0计数)
deleteCount:  表示要移除的数组元素的个数。可选的,如果省略则默认从指定的起始位置删
除到最后。

综合案例:根据数据生成柱形图

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>* {margin: 0;padding: 0;}.box {display: flex;width: 700px;height: 300px;border-left: 1px solid pink;border-bottom: 1px solid pink;margin: 100px auto;justify-content: space-around;align-items: flex-end;text-align: center;}.box>div {display: flex;width: 50px;background-color: pink;flex-direction: column;justify-content: space-between;}.box div span {margin-top: -20px;}.box div h4 {margin-bottom: -35px;width: 70px;margin-left: -10px;}</style>
</head><body><script>// 1. 四次弹框效果// 声明一个新的数组let arr = []for (let i = 1; i <= 4; i++) {// let num = prompt(`请输入第${i}季度的数据:`)// arr.push(num)arr.push(prompt(`请输入第${i}季度的数据:`))// push记得加小括号,不是等号赋值的形式}// console.log(arr)  ['123','135','345','234']// 盒子开头document.write(` <div class="box">`)// 盒子中间 利用循环的形式  跟数组有关系for (let i = 0; i < arr.length; i++) {document.write(`<div style="height: ${arr[i]}px;"><span>${arr[i]}</span><h4>第${i + 1}季度</h4></div>          `)}// 盒子结尾document.write(` </div>`)</script>
</body></html>

9.4 冒泡排序

冒泡排序是一种简单的排序算法。
它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访
数列的工作是重 复地进行直到没有再需要交换,也就是说该数列已经排序完成。

9.5 数组排序

数组. sort() 方法可以排序
let arr = [4, 2, 5, 1, 3]
// 1.升序排列写法
arr.sort(function (a, b) {
return a - b
})
console.log(arr) // [1, 2, 3, 4, 5]
// 降序排列写法
arr.sort(function (a, b) {
return b - a
})
console.log(arr) // [5, 4, 3, 2, 1]

10.函数

10.1 为什么需要函数

函数: function,是被设计为 执行特定任务 的代码
说明:函数可以把具有相同或相似逻辑的代码“包裹”起来,通过函数调用执行这些被“包裹”的代码逻辑,这么做的优势是有利于 精简代码方便复用 ,提高开发效率 。
比如我们前面使用的 alert() 、 prompt() 和 console.log() 都是一些 js 函数 ,只不过已经封装好了,我们直接使用的。

10.2 函数使用

函数的声明语法
函数名命名规范
和变量命名基本一致;尽量小驼峰式命名法;前缀应该为动词。命名建议:常用动词约定

函数的调用语法:函数名()

注意:声明(定义)的函数必须调用才会真正被执行,使用 () 调用函数

我们曾经使用的 alert() , parseInt() 这种名字后面跟小括号的本质都是函数的调用

函数体:
函数体是函数的构成部分,它负责将相同或相似代码“包裹”起来,直到函数调用时函数体内的代码才会被执行。函数的功能代码都要写在函数体当中。
函数的复用代码和循环重复代码有什么不同?
●  循环代码写完即执行,不能很方便控制执行位置。
● 函数的复用代码可 随时调用,随时执行,可重复调用。

10.3 函数传参

若函数完成功能需要调用者传入数据,那就需要有参数的函数。 这样可以极大提高函数的灵活性。
声明语法:
参数列表: 传入数据列表;声明这个函数需要传入几个数据;多个数据用逗号隔开。
调用语法:函数名(传递的参数列表)
调用函数时,需要传入几个数据就写几个,用逗号隔开。

形参:声明函数时写在函数名右边小括号里的叫形参(形式上的参数)
实参:调用函数时写在函数名右边小括号里的叫实参(实际上的参数)
形参可以理解为是 在这个函数内声明的 变量 (比如 num1 = 10)实参可以理解为是给这个变量赋值
开发中尽量保持形参和实参个数一致
我们曾经使用过的 alert('打印'), parseInt('11'), Number('11') 本质上都是函数调用的传参。
形参: 可以看做变量,但是如果一个变量不给值, 默认是 undefined  
但是如果做用户不输入实参,刚才的案例则出现 undefined + undefined 结果是 NaN
可以改进下,用户不输入实参,可以给 形参默认值 ,默认为 0, 这样程序更严谨,可以如下操作:

这个默认值只会在缺少实参参数传递时才会被执行,所以有参数会优先执行传递过来的实参, 否则默认为undefined

10.4 函数返回值

有 返回值 函数的概念: 当调用某个函数,这个函数会返回一个结果出来。
当函数需要返回数据出去时,用 return 关键字。这样 对执行结果的扩展性更高,可以让其他的程序使用这个结果。
语法:return 数据
在函数体中使用 return 关键字能将内部的执行结果交给函数外部使用。return 后面代码不会再被执行,会立即结束当前函数,所以 return 后面的数据不要换行写。 return函数可以没有 return ,这种情况 函数默认返回值为 undefined

10.5 函数细节补充

● 两个相同的函数后面的会覆盖前面的函数
● 在Javascript中 实参的个数和形参的个数可以不一致
        如果形参过多 会自动填上undefined (了解即可)
        如果实参过多 那么多余的实参会被忽略 (函数内部有一个arguments,里面装着所有的实参)
● 函数一旦碰到return就不会在往下执行了,函数的结束用return
break的结束和return结束有什么区别?
●  break用来跳出整个语句块,结束当前循环的执行。另外我们要特别注意, break语句总是跳出自己所在的那一层循环。当两个for循环嵌套时,如果break语句位于内层的for循环,它只会跳出内层的for循环,但不会跳出外层的for循环。
●  return并不是专门用来结束循环的关键字,但它可以用来结束一个方法或循环,而且还能返回return中的值。当一个方法执行到return语句时,该方法就会被结束。与break和continue不同的是, return是直接结束整个方法,不管这个return处在多少层的循环之内。

10.6 作用域

通常来说,一段程序代码中所用到的名字并不总是有效和可用的,而限定这个名字的 可用性的代码范围 就是这个名字的 作用域
作用域的使用提高了程序逻辑的局部性,增强了程序的可靠性,减少了名字冲突。

在JavaScript中,根据作用域的不同,变量可以分为:

特殊情况:
1.如果函数内部,变量没有声明,直接赋值 ,也当 全局变量 看,但是强烈不推荐
2.但是有一种情况,函数内部的形参可以看做是局部变量。
变量的访问原则:
只要是代码,就至少有一个作用域。如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域。
访问原则: 在能够访问到的情况下 先局部, 局部没有在找全局

作用域链:采取就近原则的方式来查找变量最终的值

  <script>let a = 1function fn1() {let a = 2let b = '22'fn2()function fn2() {let a = 3fn3()function fn3() {let a = 4console.log(a) //a的值 ?console.log(b) //b的值 ?}}}fn1()</script>

a 的值为4,b的值为 ‘22’

10.7 匿名函数

匿名函数: 没有名字的函数, 无法直接使用。
使用方式(有两种):1.函数表达式   2.立即执行函数。
1. 函数表达式
将匿名函数赋值给一个变量,并且通过变量名称进行调用 我们将这个称为 函数表达式
语法:
调用:
其中函数的形参和实参使用跟具名函数一致。
函数表达式要求必须先声明,再调用。
运行结果为:程序报错 
2. 立即执行函数
场景介绍: 避免全局变量之间的污染
语法:

注意: 多个立即执行函数要用 ; 隔开,要不然会报错

综合案例:转换时间案例

用户输入秒数,可以自动转换为时分秒
计算公式:计算时分秒
小时: h = parseInt(总秒数 / 60 / 60 % 24)
分钟: m = parseInt(总秒数 / 60 % 60 )
秒数: s = parseInt(总秒数 % 60)
  <script>// 1. 用户输入let second = +prompt('请输入秒数:')// 2.封装函数function getTime(t) {// 3. 转换 let h = parseInt(t / 60 / 60 % 24)let m = parseInt(t / 60 % 60)let s = parseInt(t % 60)h = h < 10 ? '0' + h : hm = m < 10 ? '0' + m : ms = s < 10 ? '0' + s : sreturn `转换完毕之后是${h}小时${m}分${s}秒`}let str = getTime(second)document.write(str)</script>

10.8 逻辑中断

开发中,还会见到以下的写法:
其实类似参数的默认值写法 
1. 逻辑运算符里的短路
短路:只存在于 && 和 || 中,当满足一定条件会让右边代码不执行
原因:通过左边能得到整个式子的结果,因此没必要再判断右边
运算结果:无论 && 还是 || ,运算结果都是最后被执行的表达式值,一般用在变量赋值

表达式1 && 表达式2:表达式1为真,返回表达式2;表达式1为假,返回表达式1

表达式1  ||  表达式2:表达式1为真,返回表达式1;表达式1为假,返回表达式2

2. 转换为Boolean型
显示转换: Boolean(内容)
记忆‘’ 、0、undefined、null、false、NaN 转换为布尔值后都是false, 其余则为 true
隐式转换:
1. 有字符串的加法 “” + 1 ,结果是 “1”
2. 减法 - (像大多数数学运算一样)只能用于数字,它会使空字符串 "" 转换为 0
3. null 经过数字转换之后会变为 0
4. undefined 经过数字转换之后会变为 NaN

10.对象

10.1 对象是什么

对象(object):JavaScript 里的一种数据类型。
可以理解为是一种 无序的数据集合 , 注意数组是有序的数据集合。 用来描述某个事物 ,例如描述一个人,人有姓名、年龄、性别等信息、还有吃饭睡觉打代码等功能。 如果用多个变量保存则比较散,用对象比较统一。

10.2 对象使用

1. 对象声明语法

2. 对象由属性和方法组成
属性:信息或叫 特征 (名词)。 比如 手机尺寸、颜色、重量等…
方法:功能或叫 行为 (动词)。 比如 手机打电话、发短信、玩游戏…
3. 属性
数据描述性的信息称为属性,如人的姓名、身高、年龄、性别等,一般是名词性的。
● 属性都是成对出现的,包括 属性名 和 值 ,它们之间使用英文 : 分隔
● 多个属性之间使用英文 , 分隔
● 属性就是依附在对象上的变量(外面是变量,对象内是属性)
● 属性名可以使用 "" 或 '', 一般情况下省略 ,除非名称遇到特殊符号如空格、中横线等
4.对象中的方法
数据行为性的信息称为方法,如跑步、唱歌等,一般是动词性的,其本质是函数。
● 方法是由方法名和函数两部分构成,它们之间使用 : 分隔
● 多个属性之间使用英文 , 分隔
● 方法是依附在对象中的函数
●  方法名可以使用 "" 或 '',一般情况下省略,除非名称遇到特殊符号如空格、中横线等

10.2 对象使用

对象本质是无序的数据集合, 操作数据无非就是 增 删 改 查

查询对象:

1. 对象名.属性

声明对象,并添加了若干属性后,可以使用 . 获得对象中属性对应的值,我称之为属性访问。
简单理解就是获得对象里面的属性值。
2. 对象[‘属性’] ( ‘’ 或 "" 都可以)
对于多词属性或则 - 等属性,点操作就不能用了。

[ ] 语法里面的值如果不添加引号 默认会当成变量解析
总结: 没有必要的时候直接使用点语法, 在需要解析变量的时候使用 [] 语法

修改属性: 对象名.属性 = 新值
增加属性: 对象名.新属性 = 新值
删除属性: delete 对象名.属性
方法调用: 声明对象,并添加了若干方法后,可以使用 . 调用对象中函数,称之为方法调用。
也可以添加形参和实参。

10.3 遍历对象

一般不用这种方式遍历数组、主要是用来遍历对象
for in语法中的 k 是一个变量, 在循环的过程中依次代表对象的属性名
由于 k 是变量, 所以必须使用 [ ] 语法解析
一定记住: k 是获得对象的 属性名对象名[k] 是获得 属性值
案例:渲染学生信息表

<!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>table {width: 600px;text-align: center;}table,th,td {border: 1px solid #ccc;border-collapse: collapse;}caption {font-size: 18px;margin-bottom: 10px;font-weight: 700;}tr {height: 40px;cursor: pointer;}table tr:nth-child(1) {background-color: #ddd;}table tr:not(:first-child):hover {background-color: #eee;}</style>
</head><body><h2>学生信息</h2><p>将数据渲染到页面中...</p><table><caption>学生列表</caption><tr><th>序号</th><th>姓名</th><th>年龄</th><th>性别</th><th>家乡</th></tr><!-- script写到这里 --><script>// 1. 数据准备let students = [{ name: '小明', age: 18, gender: '男', hometown: '河北省' },{ name: '小红', age: 19, gender: '女', hometown: '河南省' },{ name: '小刚', age: 17, gender: '男', hometown: '山西省' },{ name: '小丽', age: 18, gender: '女', hometown: '山东省' },{ name: '晓强', age: 16, gender: '女', hometown: '蓝翔技校' }]// 2. 渲染页面for (let i = 0; i < students.length; i++) {document.write(`<tr><td>${i + 1}</td><td>${students[i].name}</td><td>${students[i].age}</td><td>${students[i].gender}</td><td>${students[i].hometown}</td></tr>`)}</script></table></body></html>

10.4 内置对象

1.内置对象是什么?

JavaScript 内部提供的对象,包含各种属性和方法给开发者调用。
思考:我们之前用过内置对象吗?
document.write() 、console.log()
2.内置对象-Math
介绍: Math对象是JavaScript提供的一个“数学”对象
作用: 提供了一系列做数学运算的方法
Math对象包含的方法有:
● random:生成0-1之间的随机数(包含0不包括1)
● ceil:向上取整
● floor:向下取整
● max:找最大数
● min:找最小数
● pow:幂运算
● abs:绝对值
生成任意范围随机数
Math.random() 随机数函数, 返回一个0 - 1之间,并且包括0不包括1的随机小数 [0, 1)
如何生成0-10的随机数呢?      Math . floor ( Math . random () * ( 10 + 1 ))
如何生成5-10的随机数?          Math . floor ( Math . random () * ( 5 + 1 )) + 5
如何生成N-M之间的随机数?   Math . floor ( Math . random () * ( M - N + 1 )) + N
案例: 猜数字游戏(限定次数)
  <script>// 1. 随机生成一个数字 1~10// 取到 N ~ M 的随机整数function getRandom(N, M) {return Math.floor(Math.random() * (M - N + 1)) + N}let random = getRandom(1, 10)// 2. 设定三次  三次没猜对就直接退出let flag = true  // 开关变量 for (let i = 1; i <= 3; i++) {let num = +prompt('请输入1~10之间的一个数字:')if (num > random) {alert('您猜大了,继续')} else if (num < random) {alert('您猜小了,继续')} else {flag = falsealert('猜对了,真厉害')break}}// 写到for的外面来if (flag) {alert('次数已经用完')}</script>

案例:生成随机颜色

如果参数传递的是true或者无参数,则输出 一个随机十六进制的颜色
如果参数传递的是false,则输出 一个随机rgb的颜色
  <script>// 1. 自定义一个随机颜色函数function getRandomColor(flag = true) {if (flag) {// 3. 如果是true 则返回 #fffffflet str = '#'let arr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f']// 利用for循环随机抽6次 累加到 str里面for (let i = 1; i <= 6; i++) {// 每次要随机从数组里面抽取一个  // random 是数组的索引号 是随机的let random = Math.floor(Math.random() * arr.length)str += arr[random]}return str} else {// 4. 否则是 false 则返回 rgb(255,255,255)let r = Math.floor(Math.random() * 256)  // 255let g = Math.floor(Math.random() * 256)  // 255let b = Math.floor(Math.random() * 256)  // 255return `rgb(${r},${g},${b})`}}// 2. 调用函数 getRandomColor(布尔值)console.log(getRandomColor(false))console.log(getRandomColor(true))console.log(getRandomColor())</script>

综合案例:学成在线页面渲染案例

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>学车在线首页</title><link rel="stylesheet" href="./css/style.css"><style></style>
</head><body><!-- 4. box核心内容区域开始 --><div class="box w"><div class="box-hd"><h3>精品推荐</h3><a href="#">查看全部</a></div><div class="box-bd"><ul class="clearfix"><!-- <li><a href="#"><img src="data:images/course01.png" alt=""><h4>Think PHP 5.0 博客系统实战项目演练</h4><div class="info"><span>高级</span> • <span>1125</span>人在学习</div></a></li> --><script>let data = [{src: 'images/course01.png',title: 'Think PHP 5.0 博客系统实战项目演练',num: 1125},{src: 'images/course02.png',title: 'Android 网络动态图片加载实战',num: 357},{src: 'images/course03.png',title: 'Angular2大前端商城实战项目演练',num: 22250},{src: 'images/course04.png',title: 'AndroidAPP实战项目演练',num: 389},{src: 'images/course05.png',title: 'UGUI源码深度分析案例',num: 124},{src: 'images/course06.png',title: 'Kami2首页界面切换效果实战演练',num: 432},{src: 'images/course07.png',title: 'UNITY 从入门到精通实战案例',num: 888},{src: 'images/course08.png',title: 'Cocos 深度学习你不会错过的实战',num: 590},{src: 'images/course04.png',title: '自动添加的模块',num: 1000}]for (let i = 0; i < data.length; i++) {document.write(`<li><a href="#"><img src=${data[i].src} title="${data[i].title}"><h4>${data[i].title}</h4><div class="info"><span>高级</span> • <span>${data[i].num}</span>人在学习</div></a></li>`)}</script></ul></div></div></body></html>

附:style.css

* {margin: 0;padding: 0;
}
.w {width: 1200px;margin: auto;
}
body {background-color: #f3f5f7;
}
li {list-style: none;
}
a {text-decoration: none;
}
.clearfix:before,.clearfix:after {content:"";display:table; }.clearfix:after {clear:both;}.clearfix {*zoom:1;}   .box {margin-top: 30px;
}
.box-hd {height: 45px;
}
.box-hd h3 {float: left;font-size: 20px;color: #494949;
}
.box-hd a {float: right;font-size: 12px;color: #a5a5a5;margin-top: 10px;margin-right: 30px;
}
/* 把li 的父亲ul 修改的足够宽一行能装开5个盒子就不会换行了 */
.box-bd ul {width: 1225px;
}
.box-bd ul li {position: relative;top: 0;float: left;width: 228px;height: 270px;background-color: #fff;margin-right: 15px;margin-bottom: 15px;transition: all .3s;}
.box-bd ul li a {display: block;
}
.box-bd ul li:hover {top: -8px;box-shadow: 0 15px 30px rgb(0 0 0 / 10%);
}
.box-bd ul li img {width: 100%;
}
.box-bd ul li h4 {margin: 20px 20px 20px 25px;font-size: 14px;color: #050505;font-weight: 400;
}
.box-bd .info {margin: 0 20px 0 25px;font-size: 12px;color: #999;
}
.box-bd .info span {color: #ff7c2d;
}

拓展-术语解释

拓展- 基本数据类型和引用数据类型

简单类型又叫做基本数据类型或者 值类型 ,复杂类型又叫做 引用类型 。
● 值类型:简单数据类型/基本数据类型,在存储时变量中存储的是 值本身 ,因此叫做值类型
string ,number,boolean,undefined,null
● 引用类型:复杂数据类型,在存储时变量中存储的仅仅是 地址(引用) ,因此叫做引用数据类型
通过 new 关键字创建的对象(系统对象、自定义对象),如 Object、Array、Date等
简单数据类型存放到栈里面,引用数据类型存放到堆里面。
简单数据类型传参,是把 值复制给形参,在方法内部对形参做任何改变, 不影响外部变量。
复杂数据类型传参,把变量在栈空间里保存的堆地址复制给了形参,形参和实参保存同一个堆地址, 操作的是同一个对象。

拓展- 变量声明

变量声明: 有了变量先给const,如果发现它后面是要被修改的,再改为let
const 声明的值不能更改,而且const声明变量的时候需要里面进行初始化。 但是 对于引用数据类型 , const声明的变量,里面存的不是值,是地址
建议数组和对象使用 const 来声明。

二、Web APIs

1. Web API 基本认知

1.1 作用和分类

Web API是浏览器提供的一套操作浏览器功能和页面元素的API(BOM和DOM)。

作用: 就是使用 JS 去操作 html 和浏览器
分类: DOM (文档对象模型)、 BOM (浏览器对象模型)

1.2 什么是DOM

DOM(Document Object Model—— 文档对象模型 )是用来呈现以及与任意 HTML 或 XML文档交互的API。即DOM是浏览器提供的一套专门用来 操作网页内容 的功能。
DOM作用:开发网页内容特效和实现用户交互

1.3 DOM树

将 HTML 文档以树状结构直观的表现出来,称之为文档树或 DOM 树。
作用: 文档树直观的体现了标签与标签之间的关系

文档:一个页面就是一个文档,DOM中使用document表示

元素:页面中的所有标签都是元素,DOM中使用element表示

节点:网页中的所有内容都是节点(标签、属性、文本、注释等),DOM中使用node表示

DOM 把以上内容都看做是对象

1.4 DOM对象(重要)

● DOM 对象:浏览器根据 html 标签生成的 JS对象
所有的标签属性都可以在这个对象上面找到,修改这个对象的属性会自动映射到标签身上。
● DOM 的核心思想:把网页内容当做 对象 来处理
● document 对象:是 DOM 提供的一个 对象, 网页所有内容都在document里面。
document 提供的属性和方法都是 用来访问和操作网页内 容的。 例:document.write() 

2.获取DOM对象

查找元素DOM元素就是利用 JS 选择页面中标签元素

2.1 根据CSS选择器来获取DOM元素 (重点)

1. 选择匹配的第一个元素

语法:

document.querySelector('css选择器')
参数: 包含一个或多个有效的CSS选择器 字符串  选择器需要加符号,如类名 .box,id名 #nav
返回值: 返回CSS选择器匹配的 第一个元素 (HTMLElement对象),如果没有匹配则返回 null。
获取的元素可直接修改。
<body><div class="box">123</div><div class="box">abc</div><ul class="nav"><li>测试1</li><li>测试2</li><li>测试3</li></ul><script>// 获取匹配的第一个元素// const box = document.querySelector('div')  // 123const box = document.querySelector('.box')    //123console.log(box)// 获取 ul 第一个小 li// const li = document.querySelector('ul li')const li = document.querySelector('ul li:first-child')console.log(li)</script>
</body>
2. 选择匹配的多个元素

语法:

document.querySelectorAll('css选择器')
参数:  包含一个或多个有效的CSS选择器 字符串
返回值: CSS选择器匹配的  NodeList 对象集合
获取的对象集合不可以直接修改, 只能通过遍历的方式依次给里面的元素做修改。
<body><ul class="nav"><li>测试1</li><li>测试2</li><li>测试3</li></ul><script>const lis = document.querySelectorAll('.nav li')console.log(lis)</script>
</body>
querySelectAll() 得到的是一个 伪数组 : 有长度有索引号,但是没有 pop() push() 等数组方法 。
想要得到里面的每一个对象,则需要遍历(for)的方式获得。
    const lis = document.querySelectorAll('.nav li')for (let i = 0; i < lis.length; i++) {console.log(lis[i]) // 每一个小li对象}
注意事项:
哪怕只有一个元素,通过querySelectAll() 获取过来的也是一个 伪数组 ,里面只有一个元素而已。
若要修改可通过 变量名[0] 进行修改。
<body><p id="nav">导航栏</p><script>const p = document.querySelectorAll('#nav')p[0].style.color = 'red'</script>
</body>
querySelector() 和 querySelectorAll() 的区别:
●  querySelector()只能选择一个元素, 可以直接操作。
●  querySelectorAll() 可以选择多个元素,得到的是伪数组,需要遍历得到每一个元素。

2.2 其他获取DOM元素方法(了解)

获取特殊元素

1. 获取body元素:doucumnet.body // 返回body元素对象

2. 获取html元素:document.documentElement // 返回html元素对象

3. 操作元素内容

DOM对象都是根据标签生成的,所以操作标签本质上就是操作DOM对象。
如果想要修改标签元素的里面的 内容 ,则可以使用两种方式:
1. 元素innerText 属性
将文本内容添加/更新到任意标签位置。 显示纯文本, 不解析标签 。

<body><div class="box">我是文字的内容</div><script>// 1. 获取元素const box = document.querySelector('.box')// 2. 修改文字内容  对象.innerText 属性box.innerText = '我是一个盒子'  // 修改文字内容// box.innerText = '<strong>我是一个盒子</strong>'  // 不解析标签</script>
</body>
2. 元素.innerHTML 属性
将文本内容添加/更新到任意标签位置。 会解析标签 ,多标签建议使用模板字符。

<body><div class="box">我是文字的内容</div><script>// 获取元素const box = document.querySelector('.box')// innerHTML 解析标签// box.innerHTML = '我要更换'box.innerHTML = '<strong>我要更换</strong>'</script>
</body>
如果还在纠结到底用谁,可以选择innerHTML
案例: 年会抽奖

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>年会抽奖</title><style>.wrapper {width: 840px;height: 420px;background: url(./images/bg01.jpg) no-repeat center / cover;padding: 100px 250px;box-sizing: border-box;}</style>
</head><body><div class="wrapper"><strong>传智教育年会抽奖</strong><h1>一等奖:<span id="one">???</span></h1><h3>二等奖:<span id="two">???</span></h3><h5>三等奖:<span id="three">???</span></h5></div><script>// 1.声明数组const personArr = ['周杰伦', '刘德华', '周星驰', 'Pink老师', '张学友']// 2. 先做一等奖// 2.1 随机数 数组的下标const random = Math.floor(Math.random() * personArr.length)// console.log(personArr[random])// 2.2 获取one 元素 const one = document.querySelector('#one')// 2.3 把名字给 oneone.innerHTML = personArr[random]// 2.4 删除数组这个名字personArr.splice(random, 1)// console.log(personArr)// 3. 二等奖// 2.1 随机数 数组的下标const random2 = Math.floor(Math.random() * personArr.length)// console.log(personArr[random])// 2.2 获取one 元素 const two = document.querySelector('#two')// 2.3 把名字给 onetwo.innerHTML = personArr[random2]// 2.4 删除数组这个名字personArr.splice(random2, 1)// 4. 三等奖// 2.1 随机数 数组的下标const random3 = Math.floor(Math.random() * personArr.length)// console.log(personArr[random])// 2.2 获取one 元素 const three = document.querySelector('#three')// 2.3 把名字给 onethree.innerHTML = personArr[random3]// 2.4 删除数组这个名字personArr.splice(random3, 1)</script>
</body></html>

4.操作元素属性

4.1 操作元素常用属性

还可以通过 JS 设置/修改标签元素属性,比如通过 src更换 图片
最常见的属性比如: href、title、src 等
语法: 对象.属性 = 值

<body><img src="./images/1.webp" alt=""><script>// 1. 获取图片元素const img = document.querySelector('img')// 2. 修改图片对象的属性   对象.属性 = 值img.src = './images/2.webp'img.title = 'pink老师的艺术照'</script>
</body>

4.2 操作元素样式属性

还可以通过 JS 设置/修改标签元素的样式属性。
比如通过 轮播图小圆点自动更换颜色样式;点击按钮可以滚动图片,移动的图片的位置 left 等等
1.通过 style 属性操作CSS
语法: 对象.style.样式属性 = 值
注意:
1. 修改样式通过 style 属性引出
2. 如果属性有 - 连接符,需要转换为 小驼峰 命名法
3. 赋值的时候,需要的时候不要忘记加 css单位
4.JS修改style样式操作,产生的是行内样式,CSS权重比较高
2. 操作类名(className) 操作CSS
如果修改的样式比较多,直接通过style属性修改比较繁琐,我们可以通过借助于css类名的形式。可以同时修改多个样式。
语法: 元素.className = 'css类名'
注意:
1. 由于 class 是关键字, 所以使用  className  去代替
2. className 是使用新值 换 旧值, 如果需要添加一个类,需要保留之前的类名, 直接使用 className 赋值会覆盖以前的类名。
3. 通过 classList 操作类控制CSS
为了解决className 容易覆盖以前的类名,我们可以通过classList方式追加和删除类名。
语法:
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.box {width: 200px;height: 200px;color: #333;}.active {color: red;background-color: pink;}</style>
</head><body><div class="box active">文字</div><script>// 通过classList添加// 1. 获取元素const box = document.querySelector('.box')// 2. 修改样式// 2.1 追加类 add() 类名不加点,并且是字符串// box.classList.add('active')// 2.2 删除类  remove() 类名不加点,并且是字符串// box.classList.remove('box')// 2.3 切换类  toggle()  有还是没有啊, 有就删掉,没有就加上box.classList.toggle('active')</script>
</body></html>

案例:轮播图随机版

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>轮播图点击切换</title><style>* {box-sizing: border-box;}.slider {width: 560px;height: 400px;overflow: hidden;}.slider-wrapper {width: 100%;height: 320px;}.slider-wrapper img {width: 100%;height: 100%;display: block;}.slider-footer {height: 80px;background-color: rgb(100, 67, 68);padding: 12px 12px 0 12px;position: relative;}.slider-footer .toggle {position: absolute;right: 0;top: 12px;display: flex;}.slider-footer .toggle button {margin-right: 12px;width: 28px;height: 28px;appearance: none;border: none;background: rgba(255, 255, 255, 0.1);color: #fff;border-radius: 4px;cursor: pointer;}.slider-footer .toggle button:hover {background: rgba(255, 255, 255, 0.2);}.slider-footer p {margin: 0;color: #fff;font-size: 18px;margin-bottom: 10px;}.slider-indicator {margin: 0;padding: 0;list-style: none;display: flex;align-items: center;}.slider-indicator li {width: 8px;height: 8px;margin: 4px;border-radius: 50%;background: #fff;opacity: 0.4;cursor: pointer;}.slider-indicator li.active {width: 12px;height: 12px;opacity: 1;}</style>
</head><body><div class="slider"><div class="slider-wrapper"><img src="./images/slider01.jpg" alt="" /></div><div class="slider-footer"><p>对人类来说会不会太超前了?</p><ul class="slider-indicator"><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li></ul><div class="toggle"><button class="prev">&lt;</button><button class="next">&gt;</button></div></div></div><script>// 1. 初始数据const sliderData = [{ url: './images/slider01.jpg', title: '对人类来说会不会太超前了?', color: 'rgb(100, 67, 68)' },{ url: './images/slider02.jpg', title: '开启剑与雪的黑暗传说!', color: 'rgb(43, 35, 26)' },{ url: './images/slider03.jpg', title: '真正的jo厨出现了!', color: 'rgb(36, 31, 33)' },{ url: './images/slider04.jpg', title: '李玉刚:让世界通过B站看到东方大国文化', color: 'rgb(139, 98, 66)' },{ url: './images/slider05.jpg', title: '快来分享你的寒假日常吧~', color: 'rgb(67, 90, 92)' },{ url: './images/slider06.jpg', title: '哔哩哔哩小年YEAH', color: 'rgb(166, 131, 143)' },{ url: './images/slider07.jpg', title: '一站式解决你的电脑配置问题!!!', color: 'rgb(53, 29, 25)' },{ url: './images/slider08.jpg', title: '谁不想和小猫咪贴贴呢!', color: 'rgb(99, 72, 114)' },]// 1. 需要一个随机数 const random = parseInt(Math.random() * sliderData.length)// console.log(sliderData[random])// 2. 把对应的数据渲染到标签里面// 2.1 获取图片const img = document.querySelector('.slider-wrapper img')// 2.2. 修改图片路径  =  对象.urlimg.src = sliderData[random].url// 3. 把p里面的文字内容更换// 3.1 获取pconst p = document.querySelector('.slider-footer p')// 3.2修改pp.innerHTML = sliderData[random].title// 4. 修改背景颜色const footer = document.querySelector('.slider-footer')footer.style.backgroundColor = sliderData[random].color// 5. 小圆点const li = document.querySelector(`.slider-indicator li:nth-child(${random + 1})`)// 让当前这个小li 添加 active这个类li.classList.add('active')</script>
</body></html>

4.3 操作表单元素属性

表单很多情况也需要修改属性,比如点击眼睛,可以看到密码,本质是把表单类型转换为文本框。

获取: DOM对象.属性名
设置: DOM对象.属性名 = 新值
表单属性中添加就有效果,移除就没有效果,一律使用布尔值表示。如果为true代表添加了该属性, 如果是false 代表移除了该属性。比如: disabled、checked、selected

<body><button>点击</button><script>// 1.获取const button = document.querySelector('button')// console.log(button.disabled)  // 默认false 不禁用button.disabled = true   // 禁用按钮</script>
</body>

4.4 自定义属性

标准属性: 标签天生自带的属性,比如class、id、title等, 可以直接使用点语法操作。比如: disabled、checked、 selected
自定义属性: 在html5中推出来了专门的data-自定义属性,在标签上一律 以data-开头 ,在DOM对象上一律以 dataset对象 方式获取。

5.定时器-间歇函数

网页中经常会需要一种功能:每隔一段时间需要自动执行一段代码,不需要我们手动去触发。

例如:网页中的倒计时。要实现这种需求,需要定时器函数。

定时器函数可以开启和关闭定时器,可以根据时间自动重复执行某些代码。

1. 开启定时器

setInterval(函数, 间隔时间)

作用:每隔一段时间调用这个函数
注意:
1. 函数名字 不需要加括号
2. 定时器返回的是一个id数字

3. 间隔时间单位是毫秒(1s = 1000ms)

  <script>// setInterval(函数, 间隔时间)// 1.直接写匿名函数// setInterval(function () {//   console.log('一秒执行一次')// }, 1000)// 2.调用函数,只写函数名,不要加小括号function fn() {console.log('一秒执行一次')}let n = setInterval(fn, 1000)// setInterval('fn()', 1000)</script>
2. 关闭定时器
let 变量名 = setInterval(函数, 间隔时间)
clearInterval(变量名)
一般不会刚创建就停止,而是满足一定条件再停止。
案例: 阅读注册协议
<body><textarea name="" id="" cols="30" rows="10">用户注册协议欢迎注册成为京东用户!在您注册过程中,您需要完成我们的注册流程并通过点击同意的形式在线签署以下协议,请您务必仔细阅读、充分理解协议中的条款内容后再点击同意(尤其是以粗体或下划线标识的条款,因为这些条款可能会明确您应履行的义务或对您的权利有所限制)。【请您注意】如果您不同意以下协议全部或任何条款约定,请您停止注册。您停止注册后将仅可以浏览我们的商品信息但无法享受我们的产品或服务。如您按照注册流程提示填写信息,阅读并点击同意上述协议且完成全部注册流程后,即表示您已充分阅读、理解并接受协议的全部内容,并表明您同意我们可以依据协议内容来处理您的个人信息,并同意我们将您的订单信息共享给为完成此订单所必须的第三方合作方(详情查看</textarea><br><button class="btn" disabled>我已经阅读用户协议(5)</button><script>// 1. 获取元素const btn = document.querySelector('.btn')// console.log(btn.innerHTML)  butto按钮特殊用innerHTML// 2. 倒计时let i = 5// 2.1 开启定时器let n = setInterval(function () {i--btn.innerHTML = `我已经阅读用户协议(${i})`if (i === 0) {clearInterval(n)  // 关闭定时器// 定时器停了,我就可以开按钮btn.disabled = falsebtn.innerHTML = '同意'}}, 1000)</script>
</body>

综合案例:轮播图定时器版

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>轮播图点击切换</title><style>* {box-sizing: border-box;}.slider {width: 560px;height: 400px;overflow: hidden;}.slider-wrapper {width: 100%;height: 320px;}.slider-wrapper img {width: 100%;height: 100%;display: block;}.slider-footer {height: 80px;background-color: rgb(100, 67, 68);padding: 12px 12px 0 12px;position: relative;}.slider-footer .toggle {position: absolute;right: 0;top: 12px;display: flex;}.slider-footer .toggle button {margin-right: 12px;width: 28px;height: 28px;appearance: none;border: none;background: rgba(255, 255, 255, 0.1);color: #fff;border-radius: 4px;cursor: pointer;}.slider-footer .toggle button:hover {background: rgba(255, 255, 255, 0.2);}.slider-footer p {margin: 0;color: #fff;font-size: 18px;margin-bottom: 10px;}.slider-indicator {margin: 0;padding: 0;list-style: none;display: flex;align-items: center;}.slider-indicator li {width: 8px;height: 8px;margin: 4px;border-radius: 50%;background: #fff;opacity: 0.4;cursor: pointer;}.slider-indicator li.active {width: 12px;height: 12px;opacity: 1;}</style>
</head><body><div class="slider"><div class="slider-wrapper"><img src="./images/slider01.jpg" alt="" /></div><div class="slider-footer"><p>对人类来说会不会太超前了?</p><ul class="slider-indicator"><li class="active"></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li></ul><div class="toggle"><button class="prev">&lt;</button><button class="next">&gt;</button></div></div></div><script>// 1. 初始数据const sliderData = [{ url: './images/slider01.jpg', title: '对人类来说会不会太超前了?', color: 'rgb(100, 67, 68)' },{ url: './images/slider02.jpg', title: '开启剑与雪的黑暗传说!', color: 'rgb(43, 35, 26)' },{ url: './images/slider03.jpg', title: '真正的jo厨出现了!', color: 'rgb(36, 31, 33)' },{ url: './images/slider04.jpg', title: '李玉刚:让世界通过B站看到东方大国文化', color: 'rgb(139, 98, 66)' },{ url: './images/slider05.jpg', title: '快来分享你的寒假日常吧~', color: 'rgb(67, 90, 92)' },{ url: './images/slider06.jpg', title: '哔哩哔哩小年YEAH', color: 'rgb(166, 131, 143)' },{ url: './images/slider07.jpg', title: '一站式解决你的电脑配置问题!!!', color: 'rgb(53, 29, 25)' },{ url: './images/slider08.jpg', title: '谁不想和小猫咪贴贴呢!', color: 'rgb(99, 72, 114)' },]// 1. 获取元素 const img = document.querySelector('.slider-wrapper img')const p = document.querySelector('.slider-footer p')let i = 0  // 信号量 控制图片的张数// 2. 开启定时器setInterval(function () {i++// 无缝衔接位置  一共八张图片,到了最后一张就是 8, 数组的长度就是 8if (i >= sliderData.length) {i = 0}// 更换图片路径  img.src = sliderData[i].url// 把字写到 p里面p.innerHTML = sliderData[i].title// 小圆点// 先删除以前的activedocument.querySelector('.slider-indicator .active').classList.remove('active')// 只让当前li添加activedocument.querySelector(`.slider-indicator li:nth-child(${i + 1})`).classList.add('active')}, 1000)</script>
</body></html>

6.事件监听(绑定)

6.1 事件监听

什么是事件?

事件是在编程时系统内发生的 动作 或者发生的事情。比如用户在网页上 单击 一个按钮
什么是事件监听?
就是让程序检测是否有事件产生,一旦有事件触发,就立即调用一个函数做出响应,也称为 绑定事件或者注册事件, 比如鼠标经过显示下拉菜单,比如点击可以播放轮播图等等。
语法:

元素对象.addEventListener('事件类型', 要执行的函数)
事件监听三要素:
事件源: 事件被触发的对象 。dom元素被事件触发了,要获取dom元素
事件类型: 用什么方式触发,比如鼠标单击 click、鼠标经过 mouseover 等
事件调用的函数: 要做什么事
注意:
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>* {margin: 0;padding: 0;}h2 {text-align: center;}.box {width: 600px;margin: 50px auto;display: flex;font-size: 25px;line-height: 40px;}.qs {width: 450px;height: 40px;color: red;}.btns {text-align: center;}.btns button {width: 120px;height: 35px;margin: 0 50px;}</style>
</head><body><h2>随机点名</h2><div class="box"><span>名字是:</span><div class="qs">这里显示姓名</div></div><div class="btns"><button class="start">开始</button><button class="end">结束</button></div><script>// 数据数组const arr = ['马超', '黄忠', '赵云', '关羽', '张飞']// 定时器的全局变量let timerId = 0// 随机号要全局变量let random = 0// 业务1.开始按钮模块const qs = document.querySelector('.qs')// 1.1 获取开始按钮对象const start = document.querySelector('.start')// 1.2 添加点击事件start.addEventListener('click', function () {timerId = setInterval(function () {// 随机数random = parseInt(Math.random() * arr.length)// console.log(arr[random])qs.innerHTML = arr[random]}, 35)// 如果数组里面只有一个值了,还需要抽取吗?  不需要  让两个按钮禁用就可以if (arr.length === 1) {// start.disabled = true// end.disabled = truestart.disabled = end.disabled = true}})// 2. 关闭按钮模块const end = document.querySelector('.end')end.addEventListener('click', function () {clearInterval(timerId)// 结束了,可以删除掉当前抽取的那个数组元素arr.splice(random, 1)console.log(arr)})</script>
</body></html>

6.2 事件监听版本

事件源.on事件 = function() { }
事件源.addEventListener(事件, 事件处理函数)
区别:
on方式会被覆盖, addEventListener 方式可绑定多次,拥有事件更多特性,推荐使用

7.事件类型

案例:轮播图完整版

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>轮播图点击切换</title><style>* {box-sizing: border-box;}.slider {width: 560px;height: 400px;overflow: hidden;}.slider-wrapper {width: 100%;height: 320px;}.slider-wrapper img {width: 100%;height: 100%;display: block;}.slider-footer {height: 80px;background-color: rgb(100, 67, 68);padding: 12px 12px 0 12px;position: relative;}.slider-footer .toggle {position: absolute;right: 0;top: 12px;display: flex;}.slider-footer .toggle button {margin-right: 12px;width: 28px;height: 28px;appearance: none;border: none;background: rgba(255, 255, 255, 0.1);color: #fff;border-radius: 4px;cursor: pointer;}.slider-footer .toggle button:hover {background: rgba(255, 255, 255, 0.2);}.slider-footer p {margin: 0;color: #fff;font-size: 18px;margin-bottom: 10px;}.slider-indicator {margin: 0;padding: 0;list-style: none;display: flex;align-items: center;}.slider-indicator li {width: 8px;height: 8px;margin: 4px;border-radius: 50%;background: #fff;opacity: 0.4;cursor: pointer;}.slider-indicator li.active {width: 12px;height: 12px;opacity: 1;}</style>
</head><body><div class="slider"><div class="slider-wrapper"><img src="./images/slider01.jpg" alt="" /></div><div class="slider-footer"><p>对人类来说会不会太超前了?</p><ul class="slider-indicator"><li class="active"></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li></ul><div class="toggle"><button class="prev">&lt;</button><button class="next">&gt;</button></div></div></div><script>// 1. 初始数据const data = [{ url: './images/slider01.jpg', title: '对人类来说会不会太超前了?', color: 'rgb(100, 67, 68)' },{ url: './images/slider02.jpg', title: '开启剑与雪的黑暗传说!', color: 'rgb(43, 35, 26)' },{ url: './images/slider03.jpg', title: '真正的jo厨出现了!', color: 'rgb(36, 31, 33)' },{ url: './images/slider04.jpg', title: '李玉刚:让世界通过B站看到东方大国文化', color: 'rgb(139, 98, 66)' },{ url: './images/slider05.jpg', title: '快来分享你的寒假日常吧~', color: 'rgb(67, 90, 92)' },{ url: './images/slider06.jpg', title: '哔哩哔哩小年YEAH', color: 'rgb(166, 131, 143)' },{ url: './images/slider07.jpg', title: '一站式解决你的电脑配置问题!!!', color: 'rgb(53, 29, 25)' },{ url: './images/slider08.jpg', title: '谁不想和小猫咪贴贴呢!', color: 'rgb(99, 72, 114)' },]// 获取元素const img = document.querySelector('.slider-wrapper img')const p = document.querySelector('.slider-footer p')const footer = document.querySelector('.slider-footer')// 1. 右按钮业务// 1.1 获取右侧按钮 const next = document.querySelector('.next')let i = 0  // 信号量 控制播放图片张数// 1.2 注册点击事件next.addEventListener('click', function () {i++i = i >= data.length ? 0 : i// 调用函数toggle()})// 2. 左侧按钮业务// 2.1 获取左侧按钮 const prev = document.querySelector('.prev')// 2.2 注册点击事件prev.addEventListener('click', function () {i--i = i < 0 ? data.length - 1 : i// 调用函数toggle()})// 声明一个渲染的函数作为复用function toggle() {// 1.4 渲染对应的数据img.src = data[i].urlp.innerHTML = data[i].titlefooter.style.backgroundColor = data[i].color// 1.5 更换小圆点    先移除原来的类名, 当前li再添加 这个 类名document.querySelector('.slider-indicator .active').classList.remove('active')document.querySelector(`.slider-indicator li:nth-child(${i + 1})`).classList.add('active')}// 3. 自动播放模块let timerId = setInterval(function () {// 利用js自动调用点击事件  click()  一定加小括号调用函数next.click()}, 1000)// 4. 鼠标经过大盒子,停止定时器const slider = document.querySelector('.slider')// 注册事件slider.addEventListener('mouseenter', function () {// 停止定时器clearInterval(timerId)})// 5. 鼠标离开大盒子,开启定时器// 注册事件slider.addEventListener('mouseleave', function () {// 停止定时器if (timerId) clearInterval(timerId)// 开启定时器timerId = setInterval(function () {// 利用js自动调用点击事件  click()  一定加小括号调用函数next.click()}, 1000)})</script>
</body></html>

8.事件对象

8.1 获取事件对象

事件对象是什么?
事件对象也是个对象,这个对象里有事件触发时的相关信息 。例如:鼠标点击事件中,事件对象就存了鼠标点在哪个位置等信息。
使用场景:
可以判断用户按下哪个键,比如按下回车键可以发布新闻
可以判断鼠标点击了哪个元素,从而做相应的操作
语法:
在事件绑定的回调函数的第一个参数就是事件对象 ,一般命名为event、ev、e

8.2 事件对象常用属性

部分常用属性:
type:获取当前的事件类型
clientX/clientY:获取光标相对于浏览器可见窗口左上角的位置
offsetX/offsetY:获取光标相对于当前DOM元素左上角的位置
key:用户按下的键盘键的值,现在不提倡使用keyCode
拓展:字符串.trim()  可去除字符串左右的空格
案例: 评论回车发布

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>评论回车发布</title><style>.wrapper {min-width: 400px;max-width: 800px;display: flex;justify-content: flex-end;}.avatar {width: 48px;height: 48px;border-radius: 50%;overflow: hidden;background: url(./images/avatar.jpg) no-repeat center / cover;margin-right: 20px;}.wrapper textarea {outline: none;border-color: transparent;resize: none;background: #f5f5f5;border-radius: 4px;flex: 1;padding: 10px;transition: all 0.5s;height: 30px;}.wrapper textarea:focus {border-color: #e4e4e4;background: #fff;height: 50px;}.wrapper button {background: #00aeec;color: #fff;border: none;border-radius: 4px;margin-left: 10px;width: 70px;cursor: pointer;}.wrapper .total {margin-right: 80px;color: #999;margin-top: 5px;opacity: 0;transition: all 0.5s;}.list {min-width: 400px;max-width: 800px;display: flex;}.list .item {width: 100%;display: flex;}.list .item .info {flex: 1;border-bottom: 1px dashed #e4e4e4;padding-bottom: 10px;}.list .item p {margin: 0;}.list .item .name {color: #FB7299;font-size: 14px;font-weight: bold;}.list .item .text {color: #333;padding: 10px 0;}.list .item .time {color: #999;font-size: 12px;}</style>
</head><body><div class="wrapper"><i class="avatar"></i><textarea id="tx" placeholder="发一条友善的评论" rows="2" maxlength="200"></textarea><button>发布</button></div><div class="wrapper"><span class="total">0/200字</span></div><div class="list"><div class="item" style="display: none;"><i class="avatar"></i><div class="info"><p class="name">zhuie</p><p class="text">大家都辛苦啦,感谢各位大大的努力,能圆满完成真是太好了[笑哭][支持]</p><p class="time">2023-05-17 20:33:21</p></div></div></div><script>const tx = document.querySelector('#tx')const total = document.querySelector('.total')const item = document.querySelector('.item')const text = document.querySelector('.text')// 1. 当我们文本域获得了焦点,就让 total 显示出来tx.addEventListener('focus', function () {total.style.opacity = 1})// 2. 当我们文本域失去了焦点,就让 total 隐藏出来tx.addEventListener('blur', function () {total.style.opacity = 0})// 3. 检测用户输入tx.addEventListener('input', function () {// console.log(tx.value.length)  得到输入的长度total.innerHTML = `${tx.value.length}/200字`})// 4. 按下回车发布评论tx.addEventListener('keyup', function (e) {// 只有按下的是回车键,才会触发if (e.key === 'Enter') {// 如果用户输入的不为空就显示和打印if (tx.value.trim()) {item.style.display = 'block'// console.log(tx.value)  // 用户输入的内容text.innerHTML = tx.value}// 等我们按下回车,结束,清空文本域tx.value = ''// 按下回车之后,就要把 字符统计 复原total.innerHTML = '0/200字'}})</script>
</body></html>

9.环境对象

环境对象: 指的是函数内部特殊的 变量 this , 它代表着当前函数运行时所处的环境
作用: 弄清楚this的指向,可以让我们代码更简洁
函数的调用方式不同,this 指代的对象也不同
【谁调用, this 就是谁】 是判断 this 指向的粗略规则
直接调用函数,其实相当于是 window.函数,所以 this 指代 window

10.回调函数

如果将函数 A 做为参数传递给函数 B 时,我们称函数 A 为 回调函数
简单理解: 当一个函数当做参数来传递给另外一个函数的时候,这个函数就是 回调函数
常见的使用场景:

回调函数本质还是函数,只不过把它当成参数使用。使用匿名函数做为回调函数比较常见。

综合案例:Tab栏切换

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>tab栏切换</title><style>* {margin: 0;padding: 0;}.tab {width: 590px;height: 340px;margin: 20px;border: 1px solid #e4e4e4;}.tab-nav {width: 100%;height: 60px;line-height: 60px;display: flex;justify-content: space-between;}.tab-nav h3 {font-size: 24px;font-weight: normal;margin-left: 20px;}.tab-nav ul {list-style: none;display: flex;justify-content: flex-end;}.tab-nav ul li {margin: 0 20px;font-size: 14px;}.tab-nav ul li a {text-decoration: none;border-bottom: 2px solid transparent;color: #333;}.tab-nav ul li a.active {border-color: #e1251b;color: #e1251b;}.tab-content {padding: 0 16px;}.tab-content .item {display: none;}.tab-content .item.active {display: block;}</style>
</head><body><div class="tab"><div class="tab-nav"><h3>每日特价</h3><ul><li><a class="active" href="javascript:;">精选</a></li><li><a href="javascript:;">美食</a></li><li><a href="javascript:;">百货</a></li><li><a href="javascript:;">个护</a></li><li><a href="javascript:;">预告</a></li></ul></div><div class="tab-content"><div class="item active"><img src="./images/tab00.png" alt="" /></div><div class="item"><img src="./images/tab01.png" alt="" /></div><div class="item"><img src="./images/tab02.png" alt="" /></div><div class="item"><img src="./images/tab03.png" alt="" /></div><div class="item"><img src="./images/tab04.png" alt="" /></div></div></div><script>// 1. a 模块制作 要给 5个链接绑定鼠标经过事件// 1.1 获取 a 元素 const as = document.querySelectorAll('.tab-nav a')for (let i = 0; i < as.length; i++) {// 要给 5个链接绑定鼠标经过事件as[i].addEventListener('mouseenter', function () {  // 鼠标经过// 排他思想  // 干掉别人 移除类activedocument.querySelector('.tab-nav .active').classList.remove('active')// 我登基 我添加类 active  this 当前的那个 a this.classList.add('active')// 下面5个大盒子 一一对应  .item // 干掉别人document.querySelector('.tab-content .active').classList.remove('active')// 对应序号的那个 item 显示 添加 active 类document.querySelector(`.tab-content .item:nth-child(${i + 1})`).classList.add('active')})}</script>
</body></html>

拓展:css伪类选择器checked(选择被勾选的复选框)

重点案例:全选文本框

<!DOCTYPE html><html><head lang="en"><meta charset="UTF-8"><title></title><style>* {margin: 0;padding: 0;}table {border-collapse: collapse;border-spacing: 0;border: 1px solid #c0c0c0;width: 500px;margin: 100px auto;text-align: center;}th {background-color: #09c;font: bold 16px "微软雅黑";color: #fff;height: 24px;}td {border: 1px solid #d0d0d0;color: #404060;padding: 10px;}.allCheck {width: 80px;}</style>
</head><body><table><tr><th class="allCheck"><input type="checkbox" name="" id="checkAll"> <span class="all">全选</span></th><th>商品</th><th>商家</th><th>价格</th></tr><tr><td><input type="checkbox" name="check" class="ck"></td><td>小米手机</td><td>小米</td><td>¥1999</td></tr><tr><td><input type="checkbox" name="check" class="ck"></td><td>小米净水器</td><td>小米</td><td>¥4999</td></tr><tr><td><input type="checkbox" name="check" class="ck"></td><td>小米电视</td><td>小米</td><td>¥5999</td></tr></table><script>// 1. 获取大复选框const checkAll = document.querySelector('#checkAll')// 2. 获取所有的小复选框const cks = document.querySelectorAll('.ck')// 3. 点击大复选框  注册事件checkAll.addEventListener('click', function () {// 得到当前大复选框的选中状态// console.log(checkAll.checked)  // 得到 是 true 或者是 false// 4. 遍历所有的小复选框 让小复选框的checked  =  大复选框的 checkedfor (let i = 0; i < cks.length; i++) {cks[i].checked = this.checked}})// 5. 小复选框控制大复选框for (let i = 0; i < cks.length; i++) {// 5.1 给所有的小复选框添加点击事件cks[i].addEventListener('click', function () {// 判断选中的小复选框个数 是不是等于  总的小复选框个数// console.log(document.querySelectorAll('.ck:checked').length)// console.log(document.querySelectorAll('.ck:checked').length === cks.length)checkAll.checked = document.querySelectorAll('.ck:checked').length === cks.length})}</script>
</body></html>

11.事件流

11.1 事件流和两个阶段说明

事件流 指的是事件完整执行过程中的流动路径。
说明:假设页面里有个div,当触发事件时,会经历两个阶段,分别是捕获阶段、冒泡阶段
简单来说:捕获阶段是从父到子,冒泡阶段是从子到父
实际工作都是使用事件冒泡为主。

11.2 事件捕获

事件捕获概念: 从DOM的根元素开始去执行对应的事件 (从外到里)
代码: DOM.addEventListener(事件类型, 事件处理函数, 是否使用捕获机制)
说明:
● addEventListener第三个参数传入 true 代表是 捕获阶段 触发(很少使用)
● 若传入 false 代表 冒泡阶段 触发,默认就是false
● 若是用 L0 事件监听,则只有冒泡阶段,没有捕获

11.3 事件冒泡

事件冒泡概念: 当一个元素的事件被触发时,同样的事件将会在该元素的所有祖先元素中依次被触发。这一过程被称为事件冒泡。
简单理解:当一个元素触发事件后,会依次向上调用所有父级元素的 同名事件 。比如click事件
事件冒泡是默认存在的。L2事件监听第三个参数是 false,或者默认都是冒泡。

11.4 阻止冒泡

问题: 因为默认就有冒泡模式的存在,所以容易导致事件影响到父级元素
需求: 若想把事件就限制在当前元素内,就需要阻止事件冒泡
前提: 阻止事件冒泡需要拿到事件对象
语法: 事件对象.stopPropagation()
注意: 此方法可以阻断事件流动传播,不光在冒泡阶段有效,捕获阶段也有效
<body><div class="father"><div class="son"></div></div><script>const fa = document.querySelector('.father')const son = document.querySelector('.son')document.addEventListener('click', function () {alert('我是爷爷')})fa.addEventListener('click', function () {alert('我是爸爸')})son.addEventListener('click', function (e) {alert('我是儿子')// 阻止流动传播  事件对象.stopPropagation()e.stopPropagation()})</script>
</body>
我们某些情况下需要 阻止 默认行为 的发生,比如 阻止 链接的跳转,表单域跳转
语法: e.preventDefault()
<body><form action="http://www.itcast.cn"><input type="submit" value="免费注册"></form><script>const form = document.querySelector('form')form.addEventListener('submit', function (e) {// 阻止默认行为  提交e.preventDefault()})</script>
</body>

11.5 解绑事件

on事件方式,直接使用null覆盖偶就可以实现事件的解绑
语法:

<body><button>点击</button><script>const btn = document.querySelector('button')btn.onclick = function () {alert('点击了')// L0 事件移除解绑btn.onclick = null}</script>
</body>
addEventListener方式必须使用:
removeEventListener(事件类型, 事件处理函数, [获取捕获或者冒泡阶段])
<body><button>点击</button><script>const btn = document.querySelector('button')function fn() {alert('点击了')}btn.addEventListener('click', fn)// L2 事件移除解绑btn.removeEventListener('click', fn)</script>
</body>
注意:匿名函数无法被解绑

拓展:鼠标经过事件的区别、两种注册事件的区别

鼠标经过事件:
● mouseover 和 mouseout 会有冒泡效果
● mouseenter 和 mouseleave 没有冒泡效果 (推荐)
两种注册事件:
● 传统on注册(L0)
同一个对象,后面注册的事件会覆盖前面注册(同一个事件)
直接使用null覆盖偶就可以实现事件的解绑
都是冒泡阶段执行的
● 事件监听注册(L2)
语法: addEventListener(事件类型, 事件处理函数, 是否使用捕获)
后面注册的事件不会覆盖前面注册的事件(同一个事件)
可以通过第三个参数去确定是在冒泡或者捕获阶段执行
必须使用removeEventListener(事件类型, 事件处理函数, 获取捕获或者冒泡阶段)
匿名函数无法被解绑

12.事件委托

事件委托是利用事件流的特征解决一些开发需求的知识技巧。
优点:减少注册次数,可以提高程序性能。
原理:事件委托其实是利用 事件冒泡 的特点。 给 父元素注册事件 ,当我们触发子元素的时候,会冒泡到父元素身上,从而触发父元素的事件。
实现: 事件对象.target. tagName 可以获得真正触发事件的元素 u
如:ul.addEventListener('click' , function(){}) 执行父级点击事件

案例:tab栏切换改造

思路:
①:给 a的父级 注册点击事件,采取事件委托方式
②:如果点击的是A , 则进行排他思想,删除添加类,注意判断的方式 利用 e.target.tagName
③:因为没有索引号了,所以这里我们可以自定义属性data-id,给5个链接添加序号
④:下面大盒子获取索引号的方式 e.target.dataset.id 号, 然后进行排他思想

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>tab栏切换</title><style>* {margin: 0;padding: 0;}.tab {width: 590px;height: 340px;margin: 20px;border: 1px solid #e4e4e4;}.tab-nav {width: 100%;height: 60px;line-height: 60px;display: flex;justify-content: space-between;}.tab-nav h3 {font-size: 24px;font-weight: normal;margin-left: 20px;}.tab-nav ul {list-style: none;display: flex;justify-content: flex-end;}.tab-nav ul li {margin: 0 20px;font-size: 14px;}.tab-nav ul li a {text-decoration: none;border-bottom: 2px solid transparent;color: #333;}.tab-nav ul li a.active {border-color: #e1251b;color: #e1251b;}.tab-content {padding: 0 16px;}.tab-content .item {display: none;}.tab-content .item.active {display: block;}</style>
</head><body><div class="tab"><div class="tab-nav"><h3>每日特价</h3><ul><li><a class="active" href="javascript:;" data-id="0">精选</a></li><li><a href="javascript:;" data-id="1">美食</a></li><li><a href="javascript:;" data-id="2">百货</a></li><li><a href="javascript:;" data-id="3">个护</a></li><li><a href="javascript:;" data-id="4">预告</a></li></ul></div><div class="tab-content"><div class="item active"><img src="./images/tab00.png" alt="" /></div><div class="item"><img src="./images/tab01.png" alt="" /></div><div class="item"><img src="./images/tab02.png" alt="" /></div><div class="item"><img src="./images/tab03.png" alt="" /></div><div class="item"><img src="./images/tab04.png" alt="" /></div></div></div><script>// 采取事件委托的形式 tab栏切换// 1. 获取 ul 父元素 因为 ul只有一个const ul = document.querySelector('.tab-nav ul')// 获取 5个 item const items = document.querySelectorAll('.tab-content .item')// 2. 添加事件ul.addEventListener('click', function (e) {// console.log(e.target)  // e.target是我们点击的对象// 我们只有点击了 a 才会 进行 添加类和删除类操作 // console.log(e.target.tagName)  // e.target.tagName 点击那个对象的 标签名if (e.target.tagName === 'A') {// console.log('我选的是a')// 排他思想 ,先移除原来的active  document.querySelector('.tab-nav .active').classList.remove('active')//当前元素添加 active  是 e.target// this 指向ul 不能用this e.target.classList.add('active')// 下面大盒子模块// console.log(e.target.dataset.id)// 获取的是字符串,需转换为数字const i = +e.target.dataset.id// 排他思想 ,先移除原来的active document.querySelector('.tab-content .active').classList.remove('active')// 对应的大盒子 添加 active // document.querySelector(`.tab-content .item:nth-child(${i + 1})`).classList.add('active')items[i].classList.add('active')}})</script>
</body></html>

13.其他事件

13.1 页面加载事件

1.外部资源(如图片、外联CSS和JavaScript等)加载完毕时触发的事件
原因:有些时候需要等页面资源全部处理完了做一些事情,老代码喜欢把 script 写在 head 中,这时候直接找 dom 元素找不到。
事件名: load
监听页面所有资源加载完毕:给 window 添加 load 事件
● 注意:不光可以监听整个页面资源加载完毕,也可以针对某个资源绑定load事件
2.当初始的HTML文档被完全加载和解析完成之后,DOMContentLoaded 事件被触发,而无需等待样式表、图像等完全加载
事件名: DOMContentLoaded
监听页面DOM加载完毕:给 document 添加 DOMContentLoaded 事件

13.2 页面滚动事件

滚动条在滚动的时候持续触发的事件。很多网页需要检测用户把页面滚动到某个区域后做一些处理, 比如固定导航栏,比如返回顶部。
事件名:scroll
监听整个页面滚动:
一般给 window 或 document 添加 scroll 事件,监听某个元素的内部滚动直接给某个元素加即可。
13.2 页面滚动事件-获取位置
scrollLeft 和 scrollTop (属性):
获取被卷去的大小,获取元素内容往左、往上滚出去看不到的距离,这两个值是可 读写 的。
尽量在scroll事件里面获取被卷去的距离。
开发中,我们经常检测页面滚动的距离,比如页面滚动100像素,就可以显示一个元素,或者固定一个元素。

<script>const div = document.querySelector('div')// 页面滚动事件window.addEventListener('scroll', function () {// 获取html元素写法  // document.documentElement  const n = document.documentElement.scrollTopif (n >= 100) {div.style.display = 'block'} else {div.style.display = 'none'}})</script>

注意:document.documentElement     HTML文档返回对象为HTML元素

13.2 页面滚动事件-滚动到指定的坐标

scrollTo() 方法可把内容滚动到指定的坐标
语法:元素.scrollTo(x, y)
案例:返回顶部

    <script>// 点击返回页面顶部const backTop = document.querySelector('#backTop')backTop.addEventListener('click', function () {// 可读写// document.documentElement.scrollTop = 0window.scrollTo(0, 0)})</script>

13.3 页面尺寸事件

会在窗口尺寸改变的时候触发事件:resize

13.3 页面尺寸事件-获取元素宽高
获取元素的可见部分宽高(不包含边框,margin,滚动条等):  clientWidth和clientHeight

案例:Rem基准值​​​​​​​

13.4 元素尺寸与位置

就是通过js的方式,得到 元素在页面中的位置
●  获取宽高: offsetWidth和offsetHeight (内容 + padding + border)
获取元素的自身宽高、包含元素自身设置的宽高、padding、border。 获取的是数值,方便计算。
注意: 获取的是可视宽高, 如果盒子是隐藏的,获取的结果是0
●  获取位置:
1.offsetLeft和offsetTop
获取元素距离自己 定位父级元素 的左、上距离, 如果都没有则以 文档左上角 为准。
注意:offsetLeft和offsetTop 是只读属性

 案例:仿京东固定导航栏案例

<body><div class="header">我是顶部导航栏</div><div class="content"><div class="sk">秒杀模块</div></div><div class="backtop"><img src="./images/close2.png" alt=""><a href="javascript:;"></a></div><script>const sk = document.querySelector('.sk')const header = document.querySelector('.header')// 页面滚动事件window.addEventListener('scroll', function () {// 当页面滚动到 秒杀模块的时候,就改变 头部的 top值// 页面被卷去的头部 >=  秒杀模块的位置 offsetTopconst n = document.documentElement.scrollTopheader.style.top = n >= sk.offsetTop ? 0 : '-80px'})</script>
</body>

案例:实现bilibili 点击小滑块移动效果

  <script>// 1. 事件委托的方法 获取父元素 tabs-listconst list = document.querySelector('.tabs-list')const line = document.querySelector('.line')// 2. 注册点击事件list.addEventListener('click', function (e) {// 只有点击了A 才有触发效果if (e.target.tagName === 'A') {// 得到当前点击元素的位置// console.log(e.target.offsetLeft)// 把我们点击的a链接盒子的位置  然后移动line.style.transform = `translateX(${e.target.offsetLeft}px)`}})</script>
2. element.getBoundingClientRect()
方法返回元素的大小及其相对于视口的位置

总结

综合案例:电梯导航

  <script>// 第一大模块,页面滑动可以显示和隐藏(function () {// 获取元素const entry = document.querySelector('.xtx_entry')const elevator = document.querySelector('.xtx-elevator')// 1. 当页面滚动大于 300像素,就显示 电梯导航// 2. 给页面添加滚动事件window.addEventListener('scroll', function () {// 被卷去的头部大于 300 const n = document.documentElement.scrollTopelevator.style.opacity = n >= entry.offsetTop ? 1 : 0})// 点击返回页面顶部const backTop = document.querySelector('#backTop')backTop.addEventListener('click', function () {// 可读写// document.documentElement.scrollTop = 0window.scrollTo(0, 0)})})();// 第二第三都放到另外一个执行函数里面(function () {// 2. 点击页面可以滑动 const list = document.querySelector('.xtx-elevator-list')list.addEventListener('click', function (e) {// console.log(11)if (e.target.tagName === 'A' && e.target.dataset.name) {// 排他思想  // 先移除原来的类active // 先获取这个active的对象const old = document.querySelector('.xtx-elevator-list .active')// console.log(old)// 判断 如果原来有active类的对象,就移除类,如果开始就没有对象,就不删除,所以不报错if (old) old.classList.remove('active')// 当前元素添加 active e.target.classList.add('active')// 获得自定义属性  new   topic // console.log(e.target.dataset.name)// 根据小盒子的自定义属性值 去选择 对应的大盒子// console.log(document.querySelector(`.xtx_goods_${e.target.dataset.name}`).offsetTop)// 获得对应大盒子的 offsetTopconst top = document.querySelector(`.xtx_goods_${e.target.dataset.name}`).offsetTop// 让页面滚动到对应的位置document.documentElement.scrollTop = top}})// 3. 页面滚动,可以根据大盒子选 小盒子 添加 active 类window.addEventListener('scroll', function () {//  3.1  先移除类 // 先获取这个active的对象const old = document.querySelector('.xtx-elevator-list .active')// console.log(old)// 判断 如果原来有active类的对象,就移除类,如果开始就没有对象,就不删除,所以不报错if (old) old.classList.remove('active')// 3.2 判断页面当前滑动的位置,选择小盒子// 获取4个大盒子const news = document.querySelector('.xtx_goods_new')const popular = document.querySelector('.xtx_goods_popular')const brand = document.querySelector('.xtx_goods_brand')const topic = document.querySelector('.xtx_goods_topic')const n = document.documentElement.scrollTopif (n >= news.offsetTop && n < popular.offsetTop) {// 选择第一个小盒子document.querySelector('[data-name=new]').classList.add('active')} else if (n >= popular.offsetTop && n < brand.offsetTop) {document.querySelector('[data-name=popular]').classList.add('active')} else if (n >= brand.offsetTop && n < topic.offsetTop) {document.querySelector('[data-name=brand]').classList.add('active')} else if (n >= topic.offsetTop) {document.querySelector('[data-name=topic]').classList.add('active')}})})();</script>

14. 日期对象

JavaScript 学习笔记 超详细(b站pink老师)相关推荐

  1. CSS学习笔记(跟随b站pink老师)

    .CSS 一.CSS简介 1.1.CSS语法规范 使用HTML时,需要遵从一定的规范,CSS也是如此.熟练使用CSS对网页进行修饰,首先需要了解CSS样式规则. CSS规则由两个主要的部分构成:选择器 ...

  2. STM32学习笔记(超详细)

    查看全文 http://www.taodudu.cc/news/show-6770803.html 相关文章: STM32单片机学习笔记(超详细整理143个问题,学习必看) vsb asc_vsb电力 ...

  3. 吴恩达推荐深度学习笔记+超详细思维导图!不做学术打工人!

    关于人工智能的分支-深度学习版块的资源有很多,但是都会较为分散.小编今天对这些资源进行了整理归纳,汇编了一套学习资源(包含书籍+电子书+百篇论文+思维导图+吴恩达深度学习笔记大全+计算机视觉学术汇总) ...

  4. 【数据可视化】Matplotlib 入门到精通学习笔记(超详细)

    数据可视化是什么 如果将文本数据与图表数据相比较,人类的思维模式更适合于理解后者,原因在于图表数据更加直观且形象化,它对于人类视觉的冲击更强,这种使用图表来表示数据的方法被叫做数据可视化. 当使用图表 ...

  5. JSF学习笔记超详细,从入门到精通,持续更新中~

    JSF笔记 1.JSF概述 JavaServer Faces (JSF) 是一种用于构建Java Web 应用程序的标准框架(是Java Community Process 规定的JSR-127标准) ...

  6. mysql 8.0.26学习笔记超详细入门到精通

    目录 1.基本的SELECT语句 1.1 查询表中特定字段 1.2 字段取别名 1.3 数据去重 1.4 数据空值替换 1.5 显示表的结构 1.6 条件查询where 2.算术运算符 3.比较运算符 ...

  7. STM32学习笔记---超详细整理144个问题

    1.AHB系统总线分为APB1(36MHz)和APB2(72MHz),其中2>1,意思是APB2接高速设备: 2.Stm32f10x.h相当于reg52.h(里面有基本的位操作定义),另一个为s ...

  8. Redis学习笔记(超详细,看完必会)

    开头: 1.Redis基本概念 Redis是一个<K,V>键值对的数据库,大量操作都是在内存中完成的,读写的效率很高,因此广泛用于缓存 Redis是单线程的 Redis实际上是采用了线程封 ...

  9. JavaScript学习笔记(四)(DOM)

    JavaScript学习笔记(四) DOM 一.DOM概述 二.元素对象 2.1 获取方式 (1).通过ID获取一个元素对象,如果没有返回null (2).通过`标签名`获取一组元素对象,,如果没有返 ...

最新文章

  1. [JOISC2014]ストラップ
  2. 在线IDE之关键字另色显示
  3. 强力推荐!飞桨产业级PaddleNLP最新全景图发布
  4. Struts 体系结构与工作原理(图)
  5. XI 安装MS SQLSERVER JDBC 驱动
  6. python xlwt模块使用_Python xlwt模块使用代码实例
  7. MySQL在DOS下的基本命令操作
  8. 【qduoj - 纳新题】凑数题(恰好装满类0-1背包 或 母函数)
  9. 请给出计算231-1的python表达式_【填空题】计算2 32 -1的Python表达式可以书写为____...
  10. 哈希表和红黑树的对比
  11. 思想篇(1)--企业需要什么样的人才?
  12. L3-029 还原文件 (30 分)-PAT 团体程序设计天梯赛 GPLT
  13. ADO.NET数据访问模式
  14. 挑战程序设计竞赛:Conscription
  15. python爬虫微信_python 微信爬虫
  16. Redis中五中数据类型的实例
  17. 压电式雨量传感器数字感知降雨量
  18. java图片加水印上传工具类_基于Spring Boot实现图片上传/加水印一把梭操作
  19. foxmail邮箱怎么导入邮件_Foxmail怎样导入和导出邮箱账户和邮件
  20. Docker 容器化技术(介绍)

热门文章

  1. 古琴调音频率及音位图(正调F调)
  2. 【杂烩】Tesla M40 24G 在Win11上的双显卡显示实现、改风冷
  3. linux哪个版本支持tipc,TIPC协议和实现解析
  4. PowerMill 2018三五轴编程+后处理制作视频教程
  5. OpenCV-图像颗粒感
  6. java备忘--20190828
  7. keep-alive 的作用及使用场景
  8. Laravel 5 - Trait method can has not been applied, because there are collisions with other trai
  9. RIoTBoard开发板系列笔记(十二)—— gstreamer + vpu实现视频硬件解码播放
  10. 嵌入式监控【v4l2采集-vpu编码-live555推流】