权威网站: 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. 日期对象

14.1 实例化

14.2 日期对象方法

14.3 时间戳

15.节点操作

15.1 DOM节点

15.2 查找节点

15.3 增加节点

15.4 删除节点

16. M端事件

17.插件 

综合案例:学生信息表

18. 重绘和回流

19.Window对象

19.1 BOM

19.2 定时器-延时函数

19.3 JS 执行机制

19.4 location对象

19.5 navigator对象

19.6 histroy对象

20.本地存储

20.1 本地存储介绍

20.2 本地存储分类- localStorage

20.2 本地存储分类- sessionStorage

20.3 存储复杂数据类型

综合案例:学生就业信息表 

21.正则表达式

21.1 什么是正则表达式

21.2 语法

21.3 元字符

21.4 修饰符

综合案例:小兔鲜页面注册

阶段案例:小兔鲜登录页面

阶段案例:小兔鲜首页页面

实战案例:放大镜效果

三、JS进阶

1.作用域

1.1 局部作用域

1.2 全局作用域

1.3 作用域链

1.4 JS垃圾回收机制

拓展-JS垃圾回收机制-算法说明

1.5 闭包

1.6 变量提升

2.函数进阶

2.1 函数提升

2.2 函数参数

拓展-展开运算符

2.3 箭头函数(重要)

3.解构赋值

3.1 数组解构

注意: js 前面必须加分号情况

3.2 对象解构

综合案例:商品列表价格筛选

4.深入对象

4.1创建对象三种方式

4.2 构造函数

4.3 实例成员&静态成员

5.内置构造函数

5.1 Object

5.2 Array

5.3 String

显示赠品练习

5.4 Number

综合案例:购物车展示

6.编程思想

6.1 面向过程编程

6.2 面向对象编程 (oop)

6.3 面向过程和面向对象的对比

7. 构造函数(封装性)

8.原型

8.1 原型

 8.2 原型 - this指向

8.3 constructor 属性

8.4 对象原型

8.5 原型继承

8.6 原型链

综合案例:消息提示对象封装

9.深浅拷贝

9.1 浅拷贝

9.2 深拷贝

10.异常处理

10.1 throw 抛异常 

10.2 try/catch 捕获错误信息

10.3 debugger

11. 处理this 

11.1 this指向-普通函数

11.1 this指向-箭头函数

11.2 改变this

12. 性能优化

12.1 防抖(debounce)

12.2 节流(throttle)

Lodash 库 实现节流和防抖

​编辑

节流综合案例:页面打开,可以记录上一次的视频播放位置 

一、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标签写在

上面

   

   

注意事项:

注意事项:

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

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

3. 内联 JavaScript

代码写在标签内部

语法:

   

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用来做中间存储。

 

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.14

    console.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 = 25

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

模板字符串

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

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

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

 

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

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

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

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

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

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

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

    // 未定义类型   弱数据类型   声明一个变量未赋值就是 undefined

    let num

    console.log(num)

工作中的使用场景:

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

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

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

    //  null 空的

    let obj = null

    console.log(obj)

null 和 undefined 区别:

● undefined 表示没有赋值

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

    // 计算有区别

    console.log(undefined + 1)  // NaN

    console.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) // pink1

    console.log(2 + 2)   // 4

    console.log(2 + '2') // 22

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

    console.log(2 - 2)    // 0

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

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

小技巧:

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

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

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

5.3 显式转换

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

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

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

● Number(数据)

        转成数字类型

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

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

● parseInt(数据) 只保留整数

● parseFloat(数据) 可以保留小数

转换为字符型:

● String(数据)

● 变量.toString(进制)

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

   

   

   

    Document

   

   

订单确认

   

 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

 

7.2.3 switch语句

语法:

释义:

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

注意事项:

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

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

简单计算器案例

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取款机案例

8.for循环

1. for循环语法

作用:重复执行代码

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

2. 退出循环

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

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

了解:

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

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

for循环和while循环的区别: 

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

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

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

案例:九九乘法表

 

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: 

表示要移除的数组元素的个数。可选的,如果省略则默认从指定的起始位置删

除到最后。

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

Document

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.但是有一种情况,函数内部的形参可以看做是局部变量。

变量的访问原则:

只要是代码,就至少有一个作用域。如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域。

访问原则:

在能够访问到的情况下 先局部, 局部没有在找全局

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

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

10.7 匿名函数

匿名函数:

没有名字的函数, 无法直接使用。

使用方式(有两种):1.函数表达式   2.立即执行函数。

1. 函数表达式

将匿名函数赋值给一个变量,并且通过变量名称进行调用 我们将这个称为

函数表达式

语法:

调用:

其中函数的形参和实参使用跟具名函数一致。

函数表达式要求必须先声明,再调用。

运行结果为:程序报错 

2. 立即执行函数

场景介绍: 避免全局变量之间的污染

语法:

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

综合案例:转换时间案例

用户输入秒数,可以自动转换为时分秒

计算公式:计算时分秒

小时: h = parseInt(总秒数 / 60 / 60 % 24)

分钟: m = parseInt(总秒数 / 60 % 60 )

秒数: s = parseInt(总秒数 % 60)

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]

是获得

属性值

案例:渲染学生信息表

Document

学生信息

将数据渲染到页面中...

学生列表
序号姓名年龄性别家乡

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

案例:

猜数字游戏(限定次数)

案例:生成随机颜色

如果参数传递的是true或者无参数,则输出 一个随机十六进制的颜色

如果参数传递的是false,则输出 一个随机rgb的颜色

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

学车在线首页

精品推荐

查看全部

附: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。

获取的元素可直接修改。

123

abc

2. 选择匹配的多个元素

语法:

document.querySelectorAll('css选择器')

参数:  包含一个或多个有效的CSS选择器

字符串

返回值: CSS选择器匹配的 

NodeList 对象集合

获取的对象集合不可以直接修改, 只能通过遍历的方式依次给里面的元素做修改。

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]

进行修改。

querySelector() 和 querySelectorAll() 的区别:

● 

querySelector()只能选择一个元素, 可以直接操作。

● 

querySelectorAll() 可以选择多个元素,得到的是伪数组,需要遍历得到每一个元素。

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

获取特殊元素

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

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

3. 操作元素内容 

DOM对象都是根据标签生成的,所以操作标签本质上就是操作DOM对象。

如果想要修改标签元素的里面的

内容

,则可以使用两种方式:

1. 元素innerText 属性

将文本内容添加/更新到任意标签位置。

显示纯文本,

不解析标签

我是文字的内容

2. 元素.innerHTML 属性

将文本内容添加/更新到任意标签位置。

会解析标签

,多标签建议使用模板字符。

我是文字的内容

如果还在纠结到底用谁,可以选择innerHTML

案例:

年会抽奖

年会抽奖

传智教育年会抽奖

一等奖:???

二等奖:???

三等奖:???

4.操作元素属性

4.1 操作元素常用属性

还可以通过 JS 设置/修改标签元素属性,比如通过 src更换 图片

最常见的属性比如: href、title、src 等

语法:

对象.属性 = 值

前端 开发语言 JavaScript 学习笔记 超详细(b站pink老师)  第3张

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方式追加和删除类名。

语法:

Document

文字

案例:轮播图随机版

轮播图点击切换

前端 开发语言 JavaScript 学习笔记 超详细(b站pink老师)  第4张

4.3 操作表单元素属性

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

获取: DOM对象.属性名

设置: DOM对象.属性名 = 新值

表单属性中添加就有效果,移除就没有效果,一律使用布尔值表示。如果为true代表添加了该属性, 如果是false 代表移除了该属性。比如: disabled、checked、selected

4.4 自定义属性

标准属性:

标签天生自带的属性,比如class、id、title等, 可以直接使用点语法操作。比如: disabled、checked、 selected

自定义属性: 在html5中推出来了专门的data-自定义属性,在标签上一律

以data-开头

,在DOM对象上一律以

dataset对象

方式获取。

5.定时器-间歇函数

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

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

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

1. 开启定时器

setInterval(函数, 间隔时间)

作用:每隔一段时间调用这个函数

注意:

1. 函数名字

不需要加括号

2. 定时器返回的是一个id数字

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

2. 关闭定时器

let 变量名 = setInterval(函数, 间隔时间)

clearInterval(变量名)

一般不会刚创建就停止,而是满足一定条件再停止。

案例:

阅读注册协议


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

轮播图点击切换

前端 开发语言 JavaScript 学习笔记 超详细(b站pink老师)  第4张

6.事件监听(绑定)

6.1 事件监听

什么是事件?

事件是在编程时系统内发生的

动作

或者发生的事情。比如用户在网页上

单击

一个按钮

什么是事件监听?

就是让程序检测是否有事件产生,一旦有事件触发,就立即调用一个函数做出响应,也称为

绑定事件或者注册事件,

比如鼠标经过显示下拉菜单,比如点击可以播放轮播图等等。

语法:

元素对象.addEventListener('事件类型', 要执行的函数)

事件监听三要素:

事件源: 事件被触发的对象

。dom元素被事件触发了,要获取dom元素

事件类型:

用什么方式触发,比如鼠标单击 click、鼠标经过 mouseover 等

事件调用的函数:

要做什么事

注意:

1. 事件类型要

加引号

2. 函数是点击之后再去执行,每次点击都会执行一次

案例:随机点名

Document

随机点名

名字是:

这里显示姓名

6.2 事件监听版本

事件源.on事件 = function() { }

事件源.addEventListener(事件, 事件处理函数)

区别:

on方式会被覆盖,

addEventListener

方式可绑定多次,拥有事件更多特性,推荐使用

7.事件类型

案例:轮播图完整版

轮播图点击切换

前端 开发语言 JavaScript 学习笔记 超详细(b站pink老师)  第4张

8.事件对象

8.1 获取事件对象

事件对象是什么?

事件对象也是个对象,这个对象里有事件触发时的相关信息

。例如:鼠标点击事件中,事件对象就存了鼠标点在哪个位置等信息。

使用场景:

可以判断用户按下哪个键,比如按下回车键可以发布新闻

可以判断鼠标点击了哪个元素,从而做相应的操作

语法:

在事件绑定的回调函数的第一个参数就是事件对象

,一般命名为event、ev、e

8.2 事件对象常用属性

部分常用属性:

type:获取当前的事件类型

clientX/clientY:获取光标相对于浏览器可见窗口左上角的位置

offsetX/offsetY:获取光标相对于当前DOM元素左上角的位置

key:用户按下的键盘键的值,现在不提倡使用keyCode

拓展:字符串.trim()  可去除字符串左右的空格

案例:

评论回车发布

评论回车发布

0/200字

9.环境对象

环境对象:

指的是函数内部特殊的

变量 this

它代表着当前函数运行时所处的环境

作用:

弄清楚this的指向,可以让我们代码更简洁

函数的调用方式不同,this 指代的对象也不同

【谁调用, this 就是谁】

是判断 this 指向的粗略规则

直接调用函数,其实相当于是 window.函数,所以 this 指代 window

10.回调函数

如果将函数 A 做为参数传递给函数 B 时,我们称函数 A 为

回调函数

简单理解: 当一个函数当做参数来传递给另外一个函数的时候,这个函数就是

回调函数

常见的使用场景:

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

综合案例:Tab栏切换

tab栏切换

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

重点案例:全选文本框

全选

商品商家价格

小米手机小米¥1999

小米净水器小米¥4999

小米电视小米¥5999

11.事件流

11.1 事件流和两个阶段说明

事件流

指的是事件完整执行过程中的流动路径。

说明:假设页面里有个div,当触发事件时,会经历两个阶段,分别是捕获阶段、冒泡阶段

简单来说:捕获阶段是从父到子,冒泡阶段是从子到父

实际工作都是使用事件冒泡为主。

11.2 事件捕获

事件捕获概念: 从DOM的根元素开始去执行对应的事件 (从外到里)

代码:

DOM.addEventListener(事件类型, 事件处理函数, 是否使用捕获机制)

说明:

● addEventListener第三个参数传入

true

代表是

捕获阶段

触发(很少使用)

● 若传入

false

代表

冒泡阶段

触发,默认就是false

● 若是用 L0 事件监听,则只有冒泡阶段,没有捕获

11.3 事件冒泡

事件冒泡概念: 当一个元素的事件被触发时,同样的事件将会在该元素的所有祖先元素中依次被触发。这一过程被称为事件冒泡。

简单理解:当一个元素触发事件后,会依次向上调用所有父级元素的

同名事件

。比如click事件

事件冒泡是默认存在的。L2事件监听第三个参数是 false,或者默认都是冒泡。

11.4 阻止冒泡

问题:

因为默认就有冒泡模式的存在,所以容易导致事件影响到父级元素

需求:

若想把事件就限制在当前元素内,就需要阻止事件冒泡

前提:

阻止事件冒泡需要拿到事件对象

语法:

事件对象.stopPropagation()

注意:

此方法可以阻断事件流动传播,不光在冒泡阶段有效,捕获阶段也有效

我们某些情况下需要

阻止

默认行为

的发生,比如 阻止

链接的跳转,表单域跳转

语法:

e.preventDefault()

11.5 解绑事件

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

语法:

addEventListener方式必须使用:

removeEventListener(事件类型, 事件处理函数, [获取捕获或者冒泡阶段])

注意:匿名函数无法被解绑

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

鼠标经过事件:

● 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 号, 然后进行排他思想

tab栏切换

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像素,就可以显示一个元素,或者固定一个元素。

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

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

scrollTo() 方法可把内容滚动到指定的坐标

语法:元素.scrollTo(x, y)

案例:返回顶部

13.3 页面尺寸事件

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

13.3 页面尺寸事件-获取元素宽高

获取元素的可见部分宽高(不包含边框,margin,滚动条等): 

clientWidth和clientHeight

案例:Rem基准值

13.4 元素尺寸与位置

就是通过js的方式,得到

元素在页面中的位置

● 

获取宽高:

offsetWidth和offsetHeight

(内容 + padding + border)

获取元素的自身宽高、包含元素自身设置的宽高、padding、border。

获取的是数值,方便计算。

注意: 获取的是可视宽高, 如果盒子是隐藏的,获取的结果是0

● 

获取位置:

1.offsetLeft和offsetTop

获取元素距离自己

定位父级元素

的左、上距离,

如果都没有则以

文档左上角

为准。

注意:offsetLeft和offsetTop 是只读属性

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

我是顶部导航栏

秒杀模块

前端 开发语言 JavaScript 学习笔记 超详细(b站pink老师)  第17张

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

2.

element.getBoundingClientRect()

方法返回元素的大小及其相对于视口的位置

总结

综合案例:电梯导航

14. 日期对象

日期对象:用来表示时间的对象

作用:可以得到当前系统时间

14.1 实例化

● 在代码中发现了 new 关键字时,一般将这个操作称为

实例化

● 创建一个时间对象并获取时间

获得当前时间:

const date = new Date()

获取指定时间:

const date = new Date('2023-5-25')

14.2 日期对象方法

使用场景:因为日期对象返回的数据我们不能直接使用,所以需要转换为实际开发中常用的格式

案例:页面显示时间 

14.3 时间戳

● 使用场景: 如果计算倒计时效果,前面方法无法直接计算,需要借助于时间戳完成

● 时间戳:是指1970年01月01日00时00分00秒起至现在的

毫秒数

,是一种特殊的计量时间的方式

● 算法:

将来的时间戳 - 现在的时间戳 = 剩余时间毫秒数

剩余时间毫秒数 转换为 剩余时间的 年月日时分秒 就是 倒计时时间

比如:将来时间戳 2000ms - 现在时间戳 1000ms = 1000ms,1000ms 转换为就是 0小时0分1秒

● 三种方式获取时间戳:

1.

使用 getTime() 方法

const date = new Date()

console.log(date.getTime())

2.简写 +new Date()

重点记住 +new Date() 因为可以返回当前时间戳或者指定的时间戳

console.log(+new Date())

3. 使用 Date.now()

console.log(Date.now())

无需实例化,

但是只能得到当前的时间戳, 而前面两种可以返回指定时间的时间戳

案例:倒计时效果

15.节点操作

15.1 DOM节点

DOM节点:DOM树里每一个内容都称之为节点

节点类型:

● 

元素节点:

所有的标签 比如 body、 div,html 是根节点

● 属性节点:所有的属性 比如 href

● 文本节点:所有的文本

● 其他

15.2 查找节点

节点关系:针对的找亲戚返回的都是对象   父节点、子节点、兄弟节点

父节点查找:

parentNode

属性,返回最近一级的父节点 找不到返回为 null

例如:子元素.parentNode

子节点查找:

childNodes

属性,获得所有子节点、包括文本节点(空格、换行)、注释节点等

children 属性(重点)

仅获得所有元素节点,返回的还是一个

伪数组,

例如:父元素.children

兄弟关系查找:

1. 下一个兄弟节点:

nextElementSibling

属性

2. 上一个兄弟节点:

previousElementSibling

属性

15.3 增加节点

1.创建节点:创造出一个新的网页元素,再添加到网页内,一般先创建节点,然后插入节点

创建元素节点方法:

document.createElement('标签名')

2.追加节点:要想在界面看到,还得插入到某个父元素中

(1)

插入到父元素的最后一个子元素:

父元素.appendChild(要插入的元素)

(2)插入到父元素中某个子元素的前面:父元素.insertBefore(要插入的元素,在哪个元素前面)

3.克隆节点:元素.cloneNode(布尔值)

特殊情况下我们新增节点按如下操作: 复制一个原有的节点,把复制的节点放到指定的元素内部

cloneNode会克隆出一个跟原标签一样的元素,括号内传入布尔值。

若为true,则克隆时会包含后代节点一起克隆。若为false(默认),则克隆时不包含后代节点。

15.4 删除节点

在 JavaScript 原生 DOM 操作中,要删除元素必须通过

父元素删除。

语法:

父元素.removeChlid(子元素),

如不存在父子关系则删除不成功

删除节点和隐藏节点(display:none) 是有区别的:

隐藏节点还是存在的,但是删除,则从html中删除节点

16. M端事件

移动端也有自己独特的地方。比如

触屏事件 touch

(也称触摸事件),Android 和 IOS 都有。

touch 对象代表一个触摸点。触摸点可能是一根手指,也可能是一根触摸笔。触屏事件可响应用户手指(或触控笔)对屏幕或者触控板操作。

常见的触屏事件如下:

17.插件 

插件: 就是别人写好的一些代码,我们只需要复制对应的代码,就可以直接实现对应的效果

学习插件的基本过程

1.

熟悉官网,了解这个插件可以完成什么需求   https://www.swiper.com.cn/

2.

看在线演示,找到符合自己需求的demo    https://www.swiper.com.cn/demo/index.html

3.

查看基本使用流程    https://www.swiper.com.cn/usage/index.html

4.

查看APi文档,去配置自己的插件    https://www.swiper.com.cn/api/index.html

注意:多个swiper同时使用的时候, 类名需要注意区分

综合案例:学生信息表

学生信息管理

新增学员

姓名:

年龄:

性别:

薪资:

就业城市:

就业榜

学号姓名年龄性别薪资就业城市操作

18. 重绘和回流

1. 浏览器是如何进行界面渲染的?

a.解析(Parser)HTML,生成DOM树(DOM Tree)

b.同时解析(Parser) CSS,生成样式规则 (Style Rules)

c.根据DOM树和样式规则,生成渲染树(Render Tree)

d.进行布局 Layout(回流/重排):根据生成的渲染树,得到节点的几何信息(位置,大小)

e.进行绘制 Painting(重绘): 根据计算和获取的信息进行整个页面的绘制

f.Display: 展示在页面上

回流(重排)

当 Render Tree 中部分或者全部元素的尺寸、结构、布局等发生改变时,浏览器就会重新渲染部分或全部文档的过程称为

回流

重绘

由于节点(元素)的样式的改变并不影响它在文档流中的位置和文档布局时(比如:color、background-color、outline等),称为

重绘

重绘不一定引起回流,而回流一定会引起重绘。

19.Window对象

19.1 BOM

BOM(Browser Object Model ) 是浏览器对象模型。

● window对象是一个全局对象,也可以说是JavaScript中的顶级对象

● 像document、alert()、console.log()这些都是window的属性,基本BOM属性和方法都是window的

● 所有通过var定义在全局作用域中的变量、函数都会变成window对象的属性和方法

● window对象下的属性和方法调用的时候可以省略window

19.2 定时器-延时函数

JavaScript 内置的一个用来让代码延迟执行的函数,叫 

setTimeout

语法:

setTimeout(回调函数,等待的毫秒数)

setTimeout 仅仅只执行一次,所以可以理解为就是把一段代码延迟执行, 平时省略window

清除延时函数

let timer = setTimeout(回调函数,等待的毫秒数)

clearTimeout(timer)

注意点:

1.延时器需要等待,所以后面的代码先执行

2.

每一次调用延时器都会产生一个新的延时器

两种定时器对比:

执行的次数

● 延时函数: 执行一次

● 间歇函数:每隔一段时间就执行一次,除非手动清除

案例:5秒钟之后消失的广告

前端 开发语言 JavaScript 学习笔记 超详细(b站pink老师)  第18张

19.3 JS 执行机制

JavaScript 语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。

这是因为 Javascript 这门脚本语言诞生的使命所致——JavaScript 是为处理页面中用户的交互,以及操作 DOM 而诞生的。比如我们对某个 DOM 元素进行添加和删除操作,不能同时进行。 应该先进行添加,之后再删除。

单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。这样所导致的问题是:如果 JS 执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉。

为了解决这个问题,利用多核 CPU 的计算能力,HTML5 提出 Web Worker 标准,允许 JavaScript 脚本创建多个线程。于是,JS 中出现了

同步

异步。

同步

前一个任务结束后再执行后一个任务,程序的执行顺序与任务的排列顺序是一致的、同步的。

比如做饭的同步做法:我们要烧水煮饭,等水开了(10分钟之后),再去切菜,炒菜。

异步

你在做一件事情时,因为这件事情会花费很长时间,在做这件事时,还可以去处理其他事情。

比如做饭的异步做法,我们在烧水的同时,利用这10分钟,去切菜,炒菜。

他们的本质区别: 这条流水线上各个流程的执行顺序不同。

同步任务

同步任务都在主线程上执行,形成一个

执行栈。

异步任务

JS 的异步是通过回调函数实现的。

一般而言,异步任务有以下三种类型:

1、普通事件,如 click、resize 等

2、资源加载,如 load、error 等

3、定时器,包括 setInterval、setTimeout 等

异步任务相关添加到

任务队列

中(任务队列也称为消息队列)。

JS 执行机制

1. 先执行

执行栈中的同步任务

2

. 异步任务放入任务队列中。

3. 一旦执行栈中的所有同步任务执行完毕,系统就会按次序读取

任务队列

中的异步任务,于是被读取的异步任务结束等待状态,进入执行栈,开始执行。

由于主线程不断的重复获得任务、执行任务、再获取任务、再执行,所以这种机制被称为

事件循环(event loop)

19.4 location对象

location 的数据类型是对象,它拆分并保存了 URL 地址的各个组成部分。

常用属性和方法:

● href 属性获取完整的 URL 地址,对其赋值时用于地址的跳转

● search 属性获取地址中携带的参数,符号 ?后面部分

● hash 属性获取地址中的啥希值,符号 # 后面部分,经常用于不刷新页面,显示不同页面,比如 网易云音乐

● reload 方法用来刷新当前页面,传入参数 true 时表示强制刷新,如:location.reload(true)

案例:5秒钟之后跳转的页面

支付成功5秒钟之后跳转到首页

19.5 navigator对象

navigator的数据类型是对象,该对象下记录了浏览器自身的相关信息

常用属性和方法: 通过 userAgent 检测浏览器的版本及平台

// 检测 userAgent(浏览器信息)

!(function () {

const userAgent = navigator.userAgent

// 验证是否为Android或iPhone

const android = userAgent.match(/(Android);?[\s\/]+([\d.]+)?/)

const iphone = userAgent.match(/(iPhone\sOS)\s([\d_]+)/)

// 如果是Android或iPhone,则跳转至移动站点

if (android || iphone) {

location.href = 'http://m.itcast.cn' }

})()

19.6 histroy对象

history 的数据类型是对象,主要管理历史记录, 该对象与浏览器地址栏的操作相对应,如前进、后退、历史记录等

常用属性和方法

20.本地存储

20.1 本地存储介绍

随着互联网的快速发展,基于网页的应用越来越普遍,同时也变的越来越复杂,为了满足各种各样的需求,会经常性在本地存储大量的数据,HTML5规范提出了相关解决方案。

1、数据存储在

用户浏览器

2、设置、读取方便、甚至页面刷新不丢失数据

3、容量较大,sessionStorage和localStorage约 5M 左右

常见的使用场景:

https://todomvc.com/examples/vanilla-es6/

页面刷新数据不丢失

20.2 本地存储分类- localStorage

作用:

可以将数据永久存储在本地(用户的电脑), 除非手动删除,否则关闭页面也会存在

特性: 可以多窗口(页面)共享(同一浏览器可以共享)、以键值对的形式存储使用

语法:

存储数据:

localStorage.setItem(key, value)

获取数据:

localStorage.getItem(key)

删除数据:localStorage.removeItem(key)

20.2 本地存储分类- sessionStorage

特性:

生命周期为关闭浏览器窗口

在同一个窗口(页面)下数据可以共享

以键值对的形式存储使用

用法跟

localStorage 基本相同

20.3 存储复杂数据类型

本地只能存储字符串,无法存储复杂数据类型。

解决:

需要将复杂数据类型转换成JSON字符串,在存储到本地

语法:JSON.stringify(复杂数据类型)

问题:因为本地存储里面取出来的是字符串,不是对象,无法直接使用

解决:

把取出来的字符串转换为对象

语法:JSON.parse(JSON字符串)

综合案例:学生就业信息表 

拓展1:数组中map方法

作用:迭代数组

语法:

const arr = ['red', 'blue', 'green']

// map 方法也是遍历 处理数据 可以返回一个数组

const newArr = arr.map(function (item, i) {

// console.log(item) // 数组元素 'red'

// console.log(i) // 下标

return item + '老师'

})

console.log(newArr) // ['red老师', 'blue老师', 'green老师']

使用场景:map 可以处理数据,并且

返回新的数组

拓展2:数组中join方法

作用: join() 方法用于把数组中的所有元素转换一个字符串

语法:

参数: 数组元素是通过参数里面指定的分隔符进行分隔的

学生信息管理

新增学员

姓名:

年龄:

性别:

薪资:

就业城市:

就业榜

学号姓名年龄性别薪资就业城市操作

21.正则表达式

21.1 什么是正则表达式

正则表达式

(Regular Expression)是用于

匹配字符串中字符组合

的模式。在 JavaScript中,正则表达式也是对象。通常用来查找、替换那些符合正则表达式的文本,许多语言都支持正则表达式。

正则表达式在 JavaScript中的使用场景:

1.

例如

验证表单

:用户名表单只能输入英文字母、数字或者下划线, 昵称输入框中可以输入中文。

(

匹配

) ,比如用户名: /^[a-z0-9_-]{3,16}$/

2.

过滤掉页面内容中的一些

敏感词

(

替换

)

3.从字符串中获取我们想要的特定部分(

提取

)等 。

21.2 语法

1. 定义正则表达式语法:

const 变量名 = /表达式/

其中 / / 是正则表达式字面量,比如:const reg = /前端/

2.判断是否有符合规则的字符串:

test()

方法 用来查看正则表达式与指定的字符串是否匹配

语法:

regObj.test(被检测的字符串)  

如果正则表达式与指定的字符串匹配 ,返回true,否则false

3.检索(查找)符合规则的字符串:

exec()

方法 在一个指定字符串中执行一个搜索匹配

语法:

regObj.exec(被检测的字符串)  

如果匹配成功,exec() 方法返回一个数组,否则返回null

正则表达式检测查找 test方法和exec方法有什么区别?

● 

test方法 用于判断是否有符合规则的字符串,返回的是布尔值 找到返回true,否则false

● 

exec方法用于检索(查找)符合规则的字符串,找到返回数组,否则为 null

21.3 元字符

元字符(特殊字符):是一些具有特殊含义的字符,可以极大提高了灵活性和强大的匹配功能。

比如,规定用户只能输入英文26个英文字母,普通字符的话 abcdefghijklm….但是换成元字符写法: [a-z]

参考文档:

MDN:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Regular_Expressions

正则测试工具:

http://tool.oschina.net/regex

为了方便记忆和学习,我们对众多的元字符进行了分类:

1.边界符(表示位置,开头和结尾,必须用什么开头,用什么结尾)

正则表达式中的边界符(位置符)用来

提示字符所处的位置

,主要有两个字符

如果 ^ 和 $ 在一起,表示必须是精确匹配。 

2.量词 (表示重复次数)

量词用来

设定某个模式出现的次数

注意: 逗号左右两侧千万不要出现空格

3.字符类 (比如 \d 表示 0~9)

(1) 

[ ]

匹配字符集合,后面的字符串只要包含[ ]中任意

一个字符

,都返回 true。

a.[ ] 里面加上 - 连字符,使用

连字符 - 表示一个范围

比如:

        [a-z] 表示

a 到 z

26个英文字母都可以

        [a-zA-Z] 表示大小写都可以

        [0-9] 表示 0~9 的数字都可以

b.[ ] 里面加上

^ 取反符号

比如: [^a-z] 匹配除了小写字母以外的字符

注意要写到中括号里面

(2)

.

匹配除换行符之外的任何单个字符

(3)预定义:

指的是

某些常见模式的简写方式。

案例:用户名验证案例

21.4 修饰符

修饰符约束正则执行的某些细节行为,如是否区分大小写、是否支持多行匹配等

语法:/表达式/修饰符

i

是单词 ignore 的缩写,

正则匹配时字母不区分大小写

g

是单词 global 的缩写,

匹配所有满足正则表达式的结果

替换 replace

语法:

字符串.replace(/正则表达式/,'替换掉文本')

案例:

过滤敏感字

综合案例:小兔鲜页面注册

阶段案例:小兔鲜登录页面

阶段案例:小兔鲜首页页面

实战案例:放大镜效果

三、JS进阶

1.作用域

作用域(scope)规定了变量能够被访问的“范围”,离开了这个“范围”变量便不能被访问,

作用域分为: 局部作用域、

全局作用域

1.1 局部作用域

局部作用域分为函数作用域和块作用域。

1.

函数作用域:

在函数内部声明的变量只能在函数内部被访问,外部无法直接访问。

总结:

1. 函数内部声明的变量,在函数外部无法被访问

2. 函数的参数也是函数内部的局部变量

3. 不同函数内部声明的变量无法互相访问

4. 函数执行完毕后,函数内部的变量实际被清空了

2. 块作用域:

在JavaScript中使用{ }包裹的代码称为代码块,代码块内部声明的变量外部将

有可能

无法被访问。

总结:

1. let 声明的变量会产生块作用域,var 不会产生块作用域

2. const 声明的常量也会产生块作用域

3. 不同代码块之间的变量无法互相访问

4. 推荐使用 let 或 const

1.2 全局作用域

闭包应用:实现数据的私有

比如,我们要做个统计函数调用次数,函数调用一次,就++

闭包的作用:

1.封闭数据,实现数据私有,外部也可以访问函数内部的变量

2.闭包很有用,因为它允许将函数与其所操作的某些数据(环境)关联起来

闭包可能引起的问题:内存泄漏

1.6 变量提升

变量提升是 JavaScript 中比较“奇怪”的现象,它允许在变量声明之前即被访问(仅存在于 

var 

声明变量)

注意:

1. 变量在未声明即被访问时会报语法错误

2. 变量在var声明之前即被访问,变量的值为 undefined

3. let/const 声明的变量不存在变量提升

4. 变量提升出现在相同作用域当中

5.

实际开发中推荐先声明再访问变量

说明:

JS初学者经常花很多时间才能习惯变量提升,还经常出现一些意想不到的bug,正因为如此,ES6 引入了块级作用域,用let 或者 const声明变量,让代码写法更加规范和人性化。

变量提升的流程:

1.

先把var 变量提升到当前作用域于最前面

2.

只提升变量声明, 不提升变量赋值

3.

然后依次执行代码

不建议使用var声明变量

2.函数进阶

2.1 函数提升

函数提升与变量提升比较类似,是指函数在声明之前即可被调用。

总结:

1. 函数提升能够使函数的声明调用更灵活

2.

函数表达式不存在提升的现象

3. 函数提升出现在相同作用域当中

2.2 函数参数

1. 动态参数

arguments 是函数内部内置的伪数组变量,它包含了调用函数时传入的所有实参

arguments 动态参数的使用场景:当不确定传递多少个实参的时候

总结:

1.

arguments 是一个

伪数组

,只存在于函数中

2.

arguments 的作用是

动态获取函数的实参

3.

可以通过for循环依次得到传递过来的实参

2. 剩余参数

剩余参数允许我们将一个不定数量的参数表示为一个数组

剩余参数主要的使用场景:

用于获取多余的实参

总结:

1. ... 是语法符号,置于最末函数形参之前,用于获取

多余

的实参

2. 借助 ... 获取的剩余实参,是个

真数组

剩余参数和动态参数区别:

动态参数是伪数组,剩余参数是真数组

开发中,还是提倡多使用

剩余参数

拓展-展开运算符

展开运算符(…),将一个数组进行展开,不会修改原数组

典型运用场景: 求数组最大值(最小值)、合并数组等

展开运算符 or 剩余参数

剩余参数:

函数参数使用,得到真数组

展开运算符:

数组中使用,

数组展开

2.3 箭头函数(重要)

目的:

更简短的函数写法并且不绑定this,箭头函数的语法比函数表达式更简洁

使用场景:

箭头函数更适用于那些本来

需要匿名函数的地方

1. 基本语法

语法1:基本写法

语法2:只有一个参数可以省略小括号 语法3:如果函数体只有一行代码,可以写到一行上,并且无需写 return 直接返回值 语法4:加括号的函数体返回对象字面量表达式

总结:

1. 箭头函数属于表达式函数,因此不存在函数提升

2. 箭头函数只有一个参数时可以省略圆括号 ()

3. 箭头函数函数体只有一行代码时可以省略花括号 {},并自动做为返回值被返回

4. 加括号的函数体返回对象字面量表达式

2. 箭头函数参数

1.

普通函数有arguments 动态参数

2.

箭头函数

没有 arguments 动态参数,但是

有剩余参数

..args

3. 箭头函数 this

箭头函数不会创建自己的 this

,它只会从自己的作用域链的上一层沿用 this。

在开发中【使用箭头函数前需要考虑函数中 this 的值】,事件回调函数使用箭头函数时,this 为全局的 window,因此

DOM事件回调函数为了简便,还是不太推荐使用箭头函数

3.解构赋值

解构赋值是一种快速为变量赋值的简洁语法,本质上仍然是为变量赋值。

3.1 数组解构

数组解构是将数组的单元值

快速批量赋值

给一系列变量的

简洁语法

1.基本语法:

1. 赋值运算符 = 左侧的 [] 用于批量声明变量,右侧数组的单元值将被赋值给左侧的变量

2. 变量的顺序对应数组单元值的位置依次进行赋值操作

典型应用交互2个变量

注意: js 前面必须加分号情况

1.

立即执行函数

2. 数组解构

2.变量多 单元值少的情况 

变量的数量大于单元值数量时,多余的变量将被赋值为

undefined

3.变量少 单元值多的情况

4.利用剩余参数解决变量少 单元值多的情况

剩余参数... 获取剩余单元值,但只能置于最末位,返回的还是一个数组

5.防止有undefined传递单元值的情况,可以设置默认值

允许初始化变量的默认值,且只有单元值为 undefined 时默认值才会生效

6.按需导入,忽略某些返回值

7.支持多维数组的结构

3.2 对象解构

对象解构是将对象属性和方法快速批量赋值给一系列变量的简洁语法。

1.

基本语法:

1. 赋值运算符 = 左侧的 {} 用于批量声明变量,右侧对象的属性值将被赋值给左侧的变量

2. 对象属性的值将被赋值给与属性名

相同的

变量

3. 注意

解构的变量名不要和外面的变量名冲突

否则报错

4.对象中找不到与变量名一致的属性时变量值为 undefined

2. 给新的变量名赋值:可以从一个对象中提取变量并同时修改新的变量名

3. 数组对象解构

3. 多级对象解构

渲染商品列表案例

遍历数组 forEach 方法(重点)

forEach() 方法用于调用数组的每个元素,并将元素传递给回调函数

主要使用场景:

遍历数组的每个元素

语法:

注意:

1.

forEach 主要是遍历数组

2.

参数当前数组元素是必须要写的,索引号可选。

综合案例:商品列表价格筛选

筛选数组 filter 方法(重点)

filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素

主要使用场景:

筛选数组符合条件的元素

,并返回筛选之后元素的

新数组

语法:

返回值:

返回

数组

,包含了符合条件的所有元素。如果没有符合条件的元素则返回空数组

参数:

currentValue 必须写, index 可选

因为返回新数组,所以

不会影响原数组

4.深入对象

4.1创建对象三种方式

1. 利用对象字面量创建对象

const o = {

name:'字面量'

}

2.

利用 new Object 创建对象

3.

利用构造函数创建对象

4.2 构造函数

构造函数 :是一种特殊的函数,主要用来初始化对象

使用场景:

常规的 {...} 语法允许创建一个对象。比如我们创建了佩奇的对象,继续创建乔治的对象还需要重新写一遍,此时可以通过

构造函数

快速创建多个类似的对象

构造函数在技术上是常规函数。

不过有两个约定:

1.

它们的命名以

大写字母开头

2.

它们只能由 "

new

" 操作符来执行。

构造函数语法:

大写字母开头的函数

创建构造函数:

说明:

1. 使用 new 关键字调用函数的行为被称为

实例化

2. 实例化构造函数时没有参数时可以省略 ()

3.

构造函数内部无需写return,返回值即为新创建的对象,即自动返回创建的新对象

4. 构造函数内部的 return 返回的值无效,所以不要写return

5. new Object() new Date() 也是实例化构造函数

实例化执行过程

1. 创建新对象

2. 构造函数this指向新对象

3. 执行构造函数代码,修改this,添加新的属性

4. 返回新对象

4.3 实例成员&静态成员

实例成员:

通过构造函数创建的对象称为实例对象,实例对象中的属性和方法称为实例成员。

说明:

1.

实例对象的属性和方法即为实例成员

2. 为构造函数传入参数,动态创建

结构相同但值不同

的对象

3. 构造函数创建的实例对象

彼此独立互不影响

静态成员:

构造函数的属性和方法被称为静态成员

说明:

1.

构造函数的属性和方法被称为静态成员

2. 一般

公共特征

的属性或方法静态成员设置为静态成员

3.

静态成员方法中的 this 指向构造函数本身

5.内置构造函数

在 JavaScript 中

最主要

的数据类型有 6 种:

基本数据类型: 字符串、数值、布尔、undefined、null

引用类型: 对象

但是,我们会发现有些特殊情况:

其实字符串、数值、布尔、等基本类型也都有专门的构造函数,这些我们称为

包装类型

JS中几乎所有的数据都可以基于构造函数创建。

引用类型 :Object,Array,RegExp,Date 等

包装类型 :String,Number,Boolean 等

5.1 Object

Object 是内置的构造函数,用于创建普通对象。

但是推荐使用字面量方式声明对象,而不是 Object 构造函数

三个常用静态方法(静态方法就是只有构造函数Object可以调用的)

1.Object.keys

作用:

Object.keys 静态方法获取

对象中所有属性(键)

语法:

注意:

返回的是一个

数组

2.Object.values

作用:

Object.values 静态方法获取

对象中所有属性值

语法:

注意:

返回的是一个

数组

3.Object. assign

作用:

Object. assign 静态方法常用于

对象拷贝

使用:

经常使用的场景给对象添加属性

语法:

5.2 Array

Array 是内置的构造函数,用于创建数组。创建数组建议使用字面量创建,不用Array构造函数创建

1. 数组常见实例方法-核心方法

作用:

reduce

返回函数累计处理的结果,经常用于求和等

基本语法:arr.reduce(function(累计值, 当前元素){}, 起始值)

参数: 起始值可以省略,如果写就作为第一次累计的起始值

累计值参数:

1. 如果有起始值,则以起始值为准开始累计, 累计值 = 起始值

2. 如果没有起始值, 则累计值以数组的第一个数组元素作为起始值开始累计

3. 后面每次遍历就会用后面的数组元素 累计到

累计值

里面 (类似求和里面的 sum )

使用场景:求和运算

2. 数组常见方法-其他方法

3. 数组常见方法- 伪数组转换为真数组

静态方法

Array.from()

5.3 String

在 JavaScript 中的字符串、数值、布尔具有对象的使用特征,如具有属性和方法。

之所以具有对象特征的原因是字符串、数值、布尔类型数据是 JavaScript 底层使用 Object 构造函数“包装”来的,被称为

包装类型

1. 字符串常见实例方法

显示赠品练习

5.4 Number

Number 是内置的构造函数,用于创建数值

常用方法:

toFixed() 设置保留小数位的长度

综合案例:购物车展示

合计:1000.00

6.编程思想

6.1 面向过程编程

面向过程

就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候再一个一个的依次调用就可以了。

面向过程,就是按照我们分析好了的步骤,按照步骤解决问题。

6.2 面向对象编程 (oop)

面向对象

是把事务分解成为一个个对象,然后由对象之间分工与合作。

面向对象是以对象功能来划分问题,而不是步骤。

在面向对象程序开发思想中,每一个对象都是功能中心,具有明确分工。

面向对象编程具有

灵活、代码可复用、容易维护和开发

的优点,更适合多人合作的大型软件项目。

面向对象的特性:

封装性、继承性、多态性

6.3 面向过程和面向对象的对比

前端不同于其他语言,面向过程更多

7. 构造函数(封装性)

封装是面向对象思想中比较重要的一部分,js面向对象可以通过构造函数实现的封装。

同样的将变量和函数组合到了一起并能通过 this 实现数据的共享,所不同的是借助构造函数创建出来的实例对象之间是彼此不影响的。

总结:

1. 构造函数体现了

面向对象的封装特性

2. 构造函数实例创建的对象彼此独立、互不影响

面向对象编程的特性:比如封装性、继承性等,可以借助于构造函数来实现

但是

存在浪费内存的问题

8.原型

8.1 原型

构造函数通过原型分配的函数是所有对象所

共享的

JavaScript 规定,

每一个构造函数都有一个 prototype 属性

,指向另一个对象,所以我们也称为原型对象。这个对象可以挂载函数,对象实例化不会多次创建原型上函数,

节约内存

可以把那些不变的方法直接定义在 prototype 对象上,这样所有对象的实例都可以共享这些方法。

构造函数和原型对象中的 this 都指向 实例化的对象。

 8.2 原型 - this指向

构造函数和原型对象中的this 都指向 实例化的对象

8.3 constructor 属性

每个原型对象里面都有个constructor 属性(

constructor 构造函数

作用:

该属性

指向

该原型对象的

构造函数, 简单理解,就是指向我的爸爸(构造函数)

使用场景:

如果有多个对象的方法,我们可以给原型对象采取对象形式赋值。

但是这样就会覆盖构造函数原型对象原来的内容,这样修改后的原型对象 constructor 就不再指向当前构造函数了

此时,我们可以在修改后的原型对象中,

添加一个 constructor 指向原来的构造函数

8.4 对象原型

对象都会有一个属性 __proto__ 指向构造函数的 prototype 原型对象,之所以我们对象可以使用构造函数 prototype 原型对象的属性和方法,就是因为对象有 __proto__ 原型的存在。

注意:

__proto__ 是JS非标准属性

[[prototype]]和__proto__意义相同

用来表明当前实例对象指向哪个原型对象prototype

 

__proto__对象原型里面也有一个

constructor属性,

指向创建该实例对象的构造函数

总结(建议反复观看):

1. prototype是什么?哪里来的?

        原型(原型对象)

        构造函数都自动有原型

2. constructor属性在哪里?作用干啥的?

        prototype原型和对象原型__proto__里面都有

        都

指向

创建实例对象/原型的

构造函数

3. __proto__属性在哪里?指向谁?

        在实例对象里面

        指向原型 prototype

8.5 原型继承

继承是面向对象编程的另一个特征,通过继承进一步提升代码封装的程度,JavaScript 中大多是借助原型对象实现继承的特性。

1. 封装-

抽取公共部分

2. 继承-

让男人和女人都能继承人类公共的一些属性和方法

3. 问题:

如果我们给女人添加了一个baby的方法,发现男人自动也添加这个方法

原因:

男人和女人都同时使用了同一个对象,根据引用类型的特点,他们指向同一个对象,修改一个就会都影响

4. 解决:

需求:男人和女人不要使用同一个对象,但是不同对象里面包含相同的属性和方法

答案:构造函数    new 每次都会创建一个新的对象

5. 继承写法完善

8.6 原型链

基于原型对象的继承使得不同构造函数的原型对象关联在一起,并且这种关联的关系是一种链状的结构,我们将原型对象的链状结构关系称为

原型链

原型链-查找规则

当访问一个对象的属性(包括方法)时,首先查找这个

对象自身

有没有该属性。

如果没有就查找它的原型(也就是 __proto__指向的

prototype 原型对象

如果还没有就查找原型对象的原型(

Object的原型对象

依此类推一直找到 Object 为止(

null

__proto__对象原型的意义就在于为对象成员查找机制提供一个方向,或者说一条路线

可以使用

instanceof

运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上

综合案例:消息提示对象封装

9.深浅拷贝

9.1 浅拷贝

浅拷贝:拷贝的是地址

常见方法:

1. 拷贝对象:Object.assgin() / 展开运算符 {...obj} 拷贝对象

2.拷贝数组:Array.prototype.concat() 或者 [...arr]

如果是

简单数据类型拷贝值,引用数据类型拷贝的是地址

(简单理解: 如果是单层对象,没问题,如果有多层就有问题)

总结:

1. 直接赋值和浅拷贝有什么区别?

        直接赋值的方法,只要是对象,都会相互影响,因为是直接拷贝对象栈里面的地址

        浅拷贝如果是一层对象,不相互影响,如果出现多层对象拷贝还会相互影响

2. 浅拷贝怎么理解?

        拷贝对象之后,里面的属性值是简单数据类型直接拷贝值

        如果属性值是引用数据类型则拷贝的是地址

9.2 深拷贝

深拷贝:拷贝的是对象,不是地址

常见方法:

1.

通过递归实现深拷贝

函数递归:

如果一个函数在内部可以调用其本身,那么这个函数就是递归函数

简单理解:函数内部自己调用自己, 这个函数就是递归函数

递归函数的作用和循环效果类似

由于递归很容易发生“栈溢出”错误(stack overflow),所以

必须要加退出条件 return

利用递归函数实现 setTimeout 模拟 setInterval效果

通过递归函数实现深拷贝(简版)

2. js库lodash里面cloneDeep内部实现了深拷贝

lodash官网:Lodash 简介 | Lodash中文文档 | Lodash中文网

3. 通过JSON.stringify()实现

总结:

实现深拷贝三种方式:

1.自己利用递归函数书写深拷贝

2.利用js库 lodash里面的 _.cloneDeep()

3.利用JSON字符串转换

10.异常处理

10.1 throw 抛异常 

异常处理是指预估代码执行过程中可能发生的错误,然后最大程度的避免错误的发生导致整个程序无法继续运行。

总结: 1. throw 抛出异常信息,程序也会终止执行2. throw 后面跟的是错误提示信息 3. Error 对象配合 throw 使用,能够设置更详细的错误信息

10.2 try/catch 捕获错误信息

我们可以通过try / catch 捕获错误信息(浏览器提供的错误信息) 

123

总结: 1. try...catch 用于捕获错误信息 2. 将预估可能发生错误的代码写在 try 代码段中 3. 如果 try 代码段中出现错误后,会执行 catch 代码段,并截获到错误信息,利用catch的参数可以调用错误信息4. finally 不管是否有错误,都会执行

10.3 debugger

debugger:停止 JavaScript 的执行,相当于设置断点。

11. 处理this 

this 是 JavaScript 最具“魅惑”的知识点,不同的应用场合 this 的取值可能会有意想不到的结果,在此我们对以往学习过的关于【 this 默认的取值】情况进行归纳和总结。

11.1 this指向-普通函数

普通函数的调用方式决定了 this 的值,即【谁调用 this 的值指向谁】

普通函数没有明确调用者时 this 值为 window,严格模式下没有调用者时 this 的值为 undefined

11.1 this指向-箭头函数

箭头函数中的 this 与普通函数完全不同,不受调用方式的影响,事实上箭头函数中并不存在 this 1. 箭头函数会默认帮我们绑定外层 this 的值,所以在箭头函数中 this 的值和外层的 this 是一样的2.箭头函数中的this引用的就是最近作用域中的this 3.向外层作用域中,一层一层查找this,直到有this的定义

注意情况1: 在开发中【使用箭头函数前需要考虑函数中 this 的值】,事件回调函数使用箭头函数时,this 为全局的 window,因此DOM事件回调函数如果里面需要DOM对象的this,则不推荐使用箭头函数

注意情况2:同样由于箭头函数 this 的原因,基于原型的面向对象也不推荐采用箭头函数

总结: 1. 函数内不存在this,沿用上一级的。过程:向外层作用域中一层一层查找this,直到有this的定义 2.不适用:构造函数,原型函数,dom事件函数等等 3. 适用:需要使用上层this的地方4. 使用正确的话,它会在很多地方带来方便,后面我们会大量使用慢慢体会

11.2 改变this

1. call() –了解 使用 call 方法调用函数,同时指定被调用函数中 this 的值语法:fun.call(thisArg, arg1, arg2, ...) ● thisArg:在 fun 函数运行时指定的 this 值● arg1,arg2:传递的其他参数返回值就是函数的返回值,因为它就是调用函数

2. apply()-理解 使用 apply 方法调用函数,同时指定被调用函数中 this 的值语法:fun.apply(thisArg, [argsArray])● thisArg:在fun函数运行时指定的 this 值● argsArray:传递的值,必须包含在数组里面返回值就是函数的返回值,因为它就是调用函数 因此 apply 主要跟数组有关系,比如使用 Math.max() 求数组的最大值

call和apply的区别:● 都是调用函数,都能改变this指向● 参数不一样,apply传递的必须是数组

3. bind()-重点bind() 方法不会调用函数。但是能改变函数内部this 指向语法:fun.bind(thisArg, arg1, arg2, ...)●  thisArg:在 fun 函数运行时指定的 this 值●  arg1,arg2:传递的其他参数返回由指定的 this 值和初始化参数改造的 原函数拷贝 (新函数)因此当我们只是想改变 this 指向,并且不想调用这个函数的时候,可以使用 bind,比如改变定时器内部的this指向

call apply bind 总结相同点:都可以改变函数内部的this指向.区别点:●  call 和 apply 会调用函数, 并且改变函数内部this指向.●  call 和 apply 传递的参数不一样, call 传递参数 aru1, aru2..形式 apply 必须数组形式[arg]●  bind 不会调用函数, 可以改变函数内部this指向.主要应用场景:●  call 调用函数并且可以传递参数●  apply 经常跟数组有关系. 比如借助于数学对象实现数组最大值最小值●  bind 不调用函数,但是还想改变this指向. 比如改变定时器内部的this指向

12. 性能优化

12.1 防抖(debounce)

所谓防抖,就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。

开发使用场景- 搜索框防抖 假设输入就可以发送请求,但是不能每次输入都去发送请求,输入比较快发送请求会比较多 我们设定一个时间,假如300ms, 当输入第一个字符时候,300ms后发送请求,但是在200ms的时候又输入了一个字符,则需要再等300ms 后发送请求

案例:利用防抖来处理-鼠标滑过盒子显示文字

12.2 节流(throttle)

所谓节流,就是指连续触发事件但是在 n 秒中只执行一次函数

开发使用场景 – 小米轮播图点击效果 、 鼠标移动、页面尺寸缩放resize、滚动条滚动可以加节流

案例:利用节流来处理-鼠标滑过盒子显示文字

总结:

1.节流和防抖的区别是? ●  节流:就是指连续触发事件但是在 n 秒中只执行一次函数,比如可以利用节流实现 1s之内 只能触发一次鼠标移动事件 ●  防抖:如果在 n 秒内又触发了事件,则会重新计算函数执行时间2. 节流和防抖的使用场景是? ●  节流:鼠标移动,页面尺寸发生变化,滚动条滚动等开销比较大的情况下 ●  防抖:搜索框输入,设定每次输入完毕n秒后发送请求,如果期间还有输入,则从新计算时间

Lodash 库 实现节流和防抖

节流综合案例:页面打开,可以记录上一次的视频播放位置 

两个事件: ①:ontimeupdate 事件在视频/音频(audio/video)当前的播放位置发送改变时触发 ②:onloadeddata 事件在当前帧的数据加载完成且还没有足够的数据播放视频/音频(audio/video)的下一帧时触发

参考链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: