JavaScript学习笔记

1. JS介绍

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

2. JS的组成

A. ECMAScript

JavaScript语言基础规定了JS基础语法核心知识

  • 变量,分支语句,循环语句,对象等

B. Web APIS

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

3. JS书写位置

A. 内部JS

直接写在HTML文件中,用Script标签包住;通常将JS代码放在HTML页面底部最好

B. 外部JS

JS代码写在以.js结尾的文件中,然后在HTML的body中引入
引入方式: <script src="./1.js"></script>

C. 内联JS

代码写在标签内部

4. JS输入输出语法

A. 输出语法

  1. 语法1
1
document.write('输出的内容')

向body内输出内容

  1. 语法2
1
alert('输出的内容')

页面弹出警告对话框用于输出

  1. 语法3
1
console.log('输出的内容')

控制台输出的语句,用于程序员调试使用

B. 输入语法

1
prompt('请输入:')

显示一个对话框用于用户输入内容

5. 变量

A. 变量的使用

1. 声明变量

语法: let 变量名
声明变量由声明关键字和变量名组成,其中let是关键字
例:声明一个年龄变量

1
let age
2. 变量赋值
1
2
let age
age = 18

或者

1
let age = 18
3. 更新变量
1
2
let age = 18
age = 19
4.声明多个变量

多个变量中间用逗号隔开

1
let age = 18, uname = '前端'

B. 变量的本质

程序在内存中开辟的存放数据的小空间

C. 变量命名规则与规范

1. 规则
  • 不能用关键字
  • 只能用下划线、字母、数字和$组成,且数字不能开头
  • 区分大小写
2. 规范
  • 起名要有意义
  • 遵守小驼峰命名法,如userName

6. 数组

A. 声明语法

let 数组名 = [数据1,数据2,...,数据n]
例:

1
2
let age = [10,20,30]
let arr = ['小明','小红','小蓝']

B. 取值语法

数组名[下标]
例:

1
2
3
4
let arr = [5,4,3,2,1]
console.log(arr[0])
console.log(arr[2])
console.log(arr.length)

分别输出5,3,5

7. 常量

使用const声明的是常量,不能改变

1
const PI = 3.14

8. 数据类型

A. 分类

1. 基本数据类型

包括number数字型,string字符串型,boolean布尔型,undefined未定义型和null空类型

2. 引用数据类型

object对象

B. 数字类型(number)

包括整数、小数、正数和负数,JS是弱数据类型的语言

  • 算术运算符: +,-,*,/,%(取模)

C. 字符串类型(string)

通过单引号(‘’),双引号(“”),反引号(``)包裹的数据都叫字符串类型,推荐使用单引号(‘’)

1. 字符串拼接

使用’+’运算符实现字符串的拼接
例:

1
document.write('我是' + 'JS')

输出”我是JS”
例:

1
2
let age = 20
document.write('我今年' + age + '岁了')

输出”我今年20岁了”,当age改变时,输出也会改变

2. 模板字符串

用于拼接字符串和变量
外面用``(反引号),内容拼接变量时,用${}包住变量

1
document.write('大家好,我叫${name},今年${age}岁')

D. 布尔类型(boolean)

仅有true和false
例:

1
2
let isColl = true
console.log(isCool) //输出true

E. 未定义类型(undefined)

只有一个值undefined;只声明变量,不赋值的情况下
例:

1
2
let num
consoole.log(num) //输出undefined

F. 空类型(null)

代表空的,无
例:

1
2
let obj = null
console.log(obj) //输出null

G. 检测数据类型

使用typeof关键字检测数据类型
例:

1
2
3
4
let age = 20
let uname = 'JS'
console.log(typeof age) //输出number
console.log(typeof uname) //输出string

9. 类型转换

A. 隐式转换

  • +号两边只要有一个是字符串,都会把另一个转成字符串
  • 除了+以外的算术运算符,比如-*/等都会把数据转成数字类型

B. 显示转换

转换成数字型(使用Number)
例:

1
2
let str = '123'
console.log(Number(str)) //输出数字123

10. 运算符

A. 赋值运算符

=,+=,-=,*=,/=,%=

B. 一元运算符

自增: ++
自减: –

C. 比较运算符

>,<,>=,<=
==: 左右两边值是否相等
===: 左右两边是否类型和值都相等
!==: 左右两边是否不全等
比较结果为boolean类型,true或false,开发中判断是否相等,推荐使用===

D. 逻辑运算符

&&(与),||(或),!(非)

11. 分支语句

A. if分支语句

1. 单分支
1
if(条件){满足条件时执行的代码}
2. 双分支
1
2
if(条件){满足条件时执行的代码}
else{不满足条件时执行的代码}
3. 多分支
1
2
3
4
if(条件1){代码1}
else if(条件2){代码2}
else if(条件3){代码3}
else{代码n}

B. 三元运算符

1
条件?满足条件执行的代码:不满足条件时执行的代码

C. switch语句

1
2
3
4
5
6
7
8
9
10
11
switch(数据){
case1:
代码1
break
case2:
代码2
break
default:
代码n
break
}

12. 循环语句

A. while循环

1
2
3
while(循环条件){
要重复执行的代码(循环体)
}

例:

1
2
3
4
5
let i = 1
while (i<=3){
document.write('循环三次<br>')
i++
}

B. break和continue

  • break: 退出整个循环
  • continue: 退出本次循环

C. for循环

1
2
3
for(变量起始值;终止条件;变量变化量){
循环体
}

例:

1
2
3
for(let i = 1;i <= 3; i++){
document.write('循环三次')
}
1. 打印数组
1
2
3
4
let arr = ['a','b','c','d']
for(let i = 0;i <= 3; i++){
console.log(arr[i])
}
2. 循环嵌套
1
2
3
4
5
for(;;){
for(;;){
循环体
}
}
3. 99乘法表
1
2
3
4
5
6
for(let i = 1;i <= 9; i++){
for(let j = 1;j <= i;j++){
document.write('<span>${j}X${i} = ${i*j}</span>')
}
document.write('<br>')
}

13. 数组

数组是一种可以按顺序保存数据的数据类型

A. 数组的基本使用

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

例:

1
let arr = [1,2,'pink',true]
2. 取值数组

数组名[下标]

B. 操作数组

1. 修改
1
2
3
4
5
let arr = ['pink', 'red', 'green']
for(let i = 0; i < arr.lengh; i++){
arr[i] = arr[i] + '老师'
}
console.log(arr)
2. 新增

数组.push()将元素添加到数组末尾,并返回数组新长度

1
arr.push(元素1,...,元素n)

例:

1
2
3
let arr = ['pink','hotpink']
arr.push('red')
console.log(arr) //输出['pink','hotpink','red']

数组.unshift(新增内容)将元素添加到数组开头,并返回数组新长度

3. 删除
  • 数组.pop() 删除最后一个元素,并返回该元素的值
  • 数组.splice() 删除指定元素
1
2
arr.splice(start,deleteCount)
arr.splice(起始位置,删除几个元素)

例:

1
2
3
let arr = ['red','green','blue']
arr.splice(1,1)
console.log(arr) //输出['red','blue']
  • 数组.shift() 删除开头第一个元素,并返回该元素的值

14. 函数

A. 函数使用

1. 函数的声明
1
2
3
function 函数名(){
函数体
}

例:

1
2
3
function fun1(){
document.write('hello,world')
}
2. 函数的调用

语法: 函数名()

B. 函数传参

例:

1
2
3
4
function getSum(num1, num2){
document.write(num1 + num2)
}
getSum(10, 20) //输出30

调用函数时,需要传入几个数据就写几个,用逗号隔开

C. 函数返回值

当调用某个函数,这个函数会返回一个结果出来

1
2
3
4
5
function fn(){
return 20
}
let red = fn()
console.log(res) //输出20

return后面代码不会再被执行,会立即结束当前函数

D. 作用域

一段程序代码中用到的名字并不总是有效和可用的,而限定这个名字的可用性代码范围就是这个名字的作用域

  • 全局作用域:作用于所有代码执行的环境
  • 局部作用域:仅作用于函数内的代码环境
  • 全局变量
  • 局部变量

E. 匿名函数

  • 具名函数:function fn(){} 调用:fn()
  • 匿名函数:function(){}
1. 函数表达式
1
2
3
let fn = function(){
函数体
}

例:

1
2
3
4
let fn = function(x,y){
console.log(x + y)
}
fn(1,2) //输出3
2. 立即执行函数

(function(){})();
例:

1
2
3
(function(x,y){
console.log(x + y)
})(1,2); //输出3

无需调用,立即执行。多个立即执行函数之间用分号隔开

15. 对象

A. 对象的定义

是一种数据类型,是一只无序的数据集合

1
2
3
4
5
let obj = {
uname: 'pink老师',
age: 18,
gender: '女'
}

B. 对象使用

对象声明: let 对象名={}

  • 属性:信息或特征
  • 方法:功能或行为
1
2
3
4
let 对象名={
属性名: 属性值,
方法名: 函数
}

C. 对象的增删改查

1. 属性–查

语法:对象名.属性

1
2
3
4
5
6
let person = {
uname: '小红',
age: 18
}
console.log(person.uname) //输出'小红'
console.log(person.age) //输出18
2. 属性-改

语法: 对象名.属性 = 新值

1
2
3
4
5
6
let person = {
uname: '小红',
age: 18
}
person.age = 20
console.log(person.age) //修改为了20
3. 属性-增

语法: 对象名.新属性 = 新值

1
2
3
4
5
6
let person = {
uname: '小红',
age: 18
}
person.gender = '女'
console.log(person) //输出'小红',18,'女'
4. 属性-删

语法: delete 对象名.属性

1
delete person.gender
5. 属性-查的另一种写法

对于多词属性或则一等属性,采用对象['属性']

1
console.log(obj['num'])

D. 对象的方法(函数)

1
2
3
4
5
6
let person = {
name: '小红',
sayHi: function(){
document.write('hello,world')
}
}

方法: 方法名:函数

E. 遍历对象

1
2
3
4
5
6
7
let obj = {
uname: '小红',
age: 18}
for(let k in obj){
console.log(k) //输出'uname','age'
console.log(obj[k]) //输出'小红',18
}

k是获得对象的属性名,对象名[k]获得属性值

F. 内置对象

常用的内置对象有:

  • document.write()
  • console.log()

G. 内置对象Math

Math对象常用方法

方法 作用
Math.random() 生成0~1之间的随机数
Math.ceil() 向上取整
Math.floor() 向下取整
Math.max() 找最大数
Math.min() 找最小数
Math.pow() 幂运算
Math.abs() 绝对值

16. 声明变量用let还是const

优先使用const
除非变量后面是要被修改的,再改为let

17. API的作用和分类

作用:使用JS去操作HTML和浏览器
分类:DOM(文档对象模型),BOM(浏览器对象模型)

18. DOM

A. 定义

DOM(Document Object Model-文档对象模型)用来呈现与任意HTML或XML文档交互的API
DOM是浏览器提供的一套专门用于操作网页内容的功能

B. DOM树

将HTML文档以树状结构直观的表现出来,直观的体现了标签与标签之间的关系

C. DOM对象

浏览器根据HTML标签生成的JS对象

  • 所有的标签属性都能在这个对象上找到
  • 修改这个对象属性会自动映射到标签上

19. 获取DOM元素

查找DOM元素就是利用JS选择页面中标签元素
根据CSS选择器来获取DOM元素

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

语法: document.querySelector('CSS选择器')
例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<body>
<div class="box">123</div>
<div class="box">abc</div>
<p id="nav">导航栏</p>
<ul>
<li>测试1</li>
<li>测试2</li>
<li>测试3</li>
</ul>
<script>
const box = document.querySelector('div') //获取'123'
const box = document.querySelector('.box') //获取'123'
const nav = document.querySelector('#nav') //获取'导航栏'
const li = document.querySelector('ul li:first-child') //获取测试1
</script>
</body>

B. 选择匹配的多个元素

语法:document.querySelectorAll('CSS选择器')
返回值:CSS选择器匹配的NodeList对象集合

1
document.querySelectorAll('ul li')`

得到的是个伪数组,想要得到里面每个对象需要遍历(for)获得

1
2
3
4
5
6
7
8
9
10
11
<ul class="nav">
<li>测试1</li>
<li>测试2</li>
<li>测试3</li>
</ul>
<script>
const lis = document.querySelectorAll('.nav li')
for(let i = 0; i < lis.length; i++){
console.log(lis[i])
}
</script>

20. 操作元素内容

A. 对象.innerText

1
2
3
<div class="box">我是一段文字</div>
const box = document.querySelector('.box') //获取元素
box.innerText = '我是一个盒子' //修改页面文字内容

只显示纯文本的修改,不解析标签

B. 对象.innerHTML

会解析标签,一同修改

1
box.innerHTML = '<strong>我是一个盒子</strong>' //此时页面显示的标签会加粗

21. 操作元素属性

A. 操作元素常用属性

通过JS设置/修改标签元素属性,通过src更换图片
语法: 对象.属性 = 值
例:

1
2
3
const pic = document.querySelector('img')
pic.src = './images/2.jpg'
pic.title = '图片的修改标题'

B. 操作元素样式属性

通过JS设置/修改标签元素的样式属性

1. 通过style属性操作CSS

语法: 对象.style.样式属性 = 值

1
2
3
4
5
6
7
8
9
10
11
12
.box{
width: 200px;
height: 200px;
background-color: pink;
}
<div class="box"></div>
<script>
const box = document.querySelector('.box')
box.style.width = '300px'
box.style.backgroundColor = 'hotpink'
box.style.border = '2px solid blue'
</script>
2. 通过类名修改样式

语法: 元素.className = 'active' //active是一个CSS类名
例:

1
2
3
4
5
6
7
8
9
10
div{
width: 200px;
height: 200px;
}
.box{
width: 300px;
height: 300px;
}
const div = document.querySelector('div')
div.className = 'box' //此时div的样式被box类替换
3. 通过classList操作类控制CSS

语法:

1
2
3
元素.classList.add('类名')  //追加一个类
元素.classList.remove('类名') //删除一个类
元素.classList.toggle('类名') //切换一个类

例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
.box{
width: 200px;
height: 200px;
color: blue;
}
.active{
color: red;
background-color: pink;
}
<div class="box">文字</div>
<script>
const box = document.querySelector('.box')
box.classList.add('active') //追加类
box.classList.remove('box') //删除类
box.classList.toggle('active') //切换类
</script>

C. 操作表单元素属性

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

  • 获取:DOM对象.属性名
  • 设置:DOM对象.属性名=新值
1
2
表单.value = '用户名'
表单.type = 'password'

例:

1
2
3
4
5
6
7
<input type="text" value="电脑">
<script>
const uname = document.querySelector('input')
console.log(unmae.value) //获取值,输出"电脑"
uname.value = '我要买电脑' //设置新值
uname.type = 'password' //设置新属性
</script>

D. 自定义属性

  • 可以由我们自己定义的属性
  • 在标签上一律由”data-“开头
  • 在DOM对象上一律以”dataset”对象方式获取

22. 定时器-间歇函数

网页中的倒计时

A. 开启定时器

语法: setInterval(函数,间隔时间)
例:

1
2
3
4
function fn(){
console.log('一秒执行一次')
}
setInterval(fn,1000)

B. 关闭定时器

语法:

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

例:

1
2
3
4
5
6
function fn(){
console.log('一秒执行一次')
}
let n = setInterval(fn,1000)
console.log(n)
clearInterval(n) //关闭

23. 事件监听

用户在网页上单击一个按钮即为事件,让程序检测是否有事件产生,若有则做出响应,即为事件监听
语法: 元素对象.addEventListener('事件类型',要执行的函数)
例:点击按钮后,会弹出一个对话框

1
2
3
4
5
6
<button>点击</button>
<script>
const btn = document.querySelector('button')
btn.addEventListener('click',function(){
alert('hello')})
</script>

24. 事件类型

A. 鼠标事件

事件 含义
click 鼠标点击
mouseenter 鼠标经过
mouseleave 鼠标离开

B. 焦点事件

表单获得光标

事件 含义
focus 获得焦点
blur 失去焦点

C. 键盘事件

事件 含义
Keydown 键盘按下触发
Keyup 键盘抬起触发

D. 文本事件

input: 用户输入事件

25. 事件对象

事件对象也是对象,存储了事件触发时的相关信息

A. 获取方式

事件绑定的回调函数的第一个参数就是事件对象
一般命名为event,ev,e
语法: 元素.addEventListener('click',function(e){})
例:

1
2
3
4
5
6
7
<button>点击</button>
<script>
const btn = document.querySelector('button')
btn.addEventListener('click',function(e){
console.log(e)
})
</script>

B. 事件对象属性

常用属性 含义
type 获取当前事件类型
clientX/clientY 获取光标相对于浏览器可见窗口左上角的位置
offsetX/offsetY 获取光标相对于当前DOM元素左上角的位置
key 用户按下键盘键的值

26. 环境对象

指的是函数内部特殊的变量this,代表当前函数运行时所处的环境

  • 普通函数里的this指的是window
  • 谁调用,this就是谁

27. 回调函数

如果将函数A作为参数传递给函数B,称函数A为回调函数

28. 事件流

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

  • 捕获阶段:从大到小,父到子
  • 冒泡阶段:从小到大,子到父

29. 事件捕获

从DOM的根元素开始执行对应事件(从外到里)
事件捕获需写对应代码才能看到效果
代码:

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

30. 事件冒泡

  • 当一个元素的事件被触发时,同样的事件将会在该元素的所有祖先元素中依次被触发
  • 当一个元素触发事件后,会依次向上调用所有父级元素的同名事件
    例:
1
2
3
4
5
6
7
8
9
10
11
const father = document.querySelector('.father')
const son = document.querySelector('.son')
document.addEventListener('click',function(){
alert('我是1')
})
fa.addEventListener('click',funtion(){
alert('我是2')
})
son.addEventListener('click',funtion(){
alert('我是3')
})

31. 阻止冒泡

语法: 事件对象.stopPropagation()

32. 解绑事件

A. on事件方式

直接使用null覆盖就可以实现事件的解绑

B. removeEventListener()

若使用addEventListener方式,必须使用removeEventListener(事件类型,事件处理函数,[获取捕获或者冒泡阶段])
例:

1
2
3
4
5
6
7
8
<button>点击</button>
<script>
const btn = document.querySelector('button')
function fn(){
alert('点击了')
}
btn.addEventListener('click',fn)
btn.removeEventListener('click',fn)

33. 阻止默认行为

语法: e.preventDefault()
例:

1
2
3
4
5
6
7
8
9
<form action = "http://www.baidu.com">
<input type = "submit" value = "免费注册">
</form>
<script>
const form = document.querySelector('form')
form.addEventListener('submit',function(e){
e.preventDefault()
})
</script>

34. 页面加载事件

加载外部资源,加载完毕时触发的事件

A. load事件(慢)

监听页面所有资源加载完毕:给window添加load事件

1
2
3
window.addEventListener('load',function(){
//执行的操作
})

B. DOMContentLoaded事件(快)

当初始的HTML文档被完全加载和解析完成之后,事件被触发,无需等待样式表、图像等完全加载
监听页面DOM加载完毕:给document添加DOMContentLoaded事件

1
2
3
document.addEventListener('DOMContentLoaded',function(){
//执行的操作
})

35. 页面滚动事件

滚动条在滚动时持续触发的事件
事件名:scroll
监听整个页面滚动

1
2
3
window.addEventListener('scroll',function(){
//执行的操作
})

36. 页面尺寸事件

语法: resize事件
在窗口尺寸改变时触发事件

1
2
3
window.addEventListener('resize',function(){
//执行的操作
})

检测屏幕宽度

1
2
3
4
window.addEventListener('resize',function(){
let w = document.documentElement.clientWidth
console.log(w)
})

37. 日期对象

让网页显示日期,可以得到当前系统时间

A. 实例化

在代码中发现new关键字时,这种操作称为实例化
创建一个时间对象并获取时间:

1
const date = new Date()   //获取当前时间
1
2
const date = new Date('2000-1-1')  
console.log(date) //获取指定时间

B. 日期对象方法

方法 作用 说明
getFullYear() 获取年份 获取四位年份
getMonth() 获取月份 取值为0~11
getDate() 获取月份每一天 不同月份取值也不相同
getDay() 获取星期几 取值为0~6
getHours() 获取小时 取值为0~23
getMinutes() 获取分钟 取值为0~59
getSeconds() 获取秒 取值为0~59

例:

1
2
3
const date = new Date()
console.log(date.getFullYear())
console.log(date.getMonth() + 1)

C. 时间戳

是指1970年1月1日0时0分0秒到现在的毫秒数。常用于实现倒计时效果
算法:

  • 将来的时间戳 - 现在的时间戳 = 剩余时间毫秒数
  • 剩余时间毫秒数转换为年月日时分秒 = 倒计时时间
1. getTime()方法

需要实例化

2. +new Date()(推荐使用)

无需实例化

3. Date.now()

无需实例化
例:

1
2
3
4
const date = new Date()
console.log(date.getTime()) //getTime()
console.log(+new Date()) //+new Date
console.log(Date.now()) //Date.now()

38. 节点操作

A. DOM节点

DOM树中每个内容都是节点

  • 元素节点:所有的标签,比如body、div
  • 属性节点:所有的属性,比如href
  • 文本节点:所有的文本

B. 查找节点

根据节点关系查找相应的节点

1. 父节点查找

parentNode属性,返回最近一级的父节点,找不到返回NULL
子元素.parentNode

1
2
3
4
5
6
7
8
9
10
<div class="box">
我是广告
<div class="box1">X</div>
</div>
<script>
const box1 = document.querySelector('.box1')
box1.addEventListener('click', function () {
this.parentNode.style.display = 'none'
})
I</script>
2. 子节点查找
  • childNodes
  • children属性(重点)
    获得所有元素的节点,返回一个伪数组
    父元素.children
    例:
1
2
3
4
5
6
7
8
9
10
11
12
13
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<script>
const ul = document.querySelector('ul')
console.log(ul.children) //得到伪数组,全儿子选择
</script>
</body>
3. 兄弟关系查找
  • 下一个兄弟节点 nextElementSibling属性
  • 上一个兄弟节点 previousElementSibling属性

例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<script>
const li2 = document.querySelector('ul li:nth-child(2)')
console.log(li2.previousElementSibling) //上一个兄弟
console.log(li2.nextElementSibling) //下一个兄弟
</script>
</body>

C. 增加节点

1. 创建节点

document.createElement('标签名')

2. 追加节点
  • 插入到父元素的最后一个子元素
    父元素.appendChild(要插入的元素)
  • 插入到父元素中某个子元素的前面
    父元素.insertBefore(要插入的元素,在哪个元素前面)
1
2
3
4
5
6
7
8
9
<ul>
<li>第一</li>
</ul>
<script>
const div = document.createElement('div')
console.log(div)
document.body.appendChild(div) //作为最后一个子元素
ul.insertBefore(li, ul.children[0]) //放在最前面一个元素
</script>

D. 克隆节点

元素.cloneNode(布尔值) 克隆一个已有元素节点
例:

1
2
3
4
5
6
7
8
9
10
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
const ul = document.querySelector('ul')
const li1 = ul.children[0].cloneNode(true) //克隆
ul.appendChild(li1) //添加
</script>

E. 删除节点

父元素.removeChild(要删除的元素)
例:

1
2
3
4
5
6
7
<ul>
<li>没用了</li>
</ul>
<script>
const ul = document.querySelector('ul')
ul.removeChild(ul.children[0])
</script>

39. M端事件

触屏事件touch

触屏touch事件 说明
touchstart 手指触摸到一个DOM元素时触发
touchmove 手指在一个DOM元素上滑动时触发
touchend 手指从一个DOM元素上移开触发

40. Window对象

A. BOM(浏览器对象模型)

window对象是全局对象,是JS的顶级对象

B. 定时器-延时函数

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

1
2
3
setTimeout(function(){
console.log('时间到了')
},2000) //延时两秒输出'时间到了'

清除延时函数:

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

C. JS执行机制

JS是单线程的,同一个时间只能做一件事。

  • 同步任务(立刻执行)
    在主线程上依次执行,形成一个执行栈

  • 异步任务(耗时)
    通过回调函数实现,异步任务添加到任务队列

    1. 普通事件:如click,resize等
    2. 资源加载:如load,error等
    3. 定时器:如setInterval,setTimeout等
  • 执行机制

    1. 先执行执行栈中的同步任务
    2. 异步任务放在任务队列
    3. 当执行栈中所有同步任务执行完毕,系统按次序读取任务队列中的异步任务,被读取的异步任务结束等待状态,进入执行栈,开始执行

D. location对象

location拆分并保存URL地址的各个组成部分

  • href利用JS的方法跳转页面
1
location.href = 'http://www.baidu.com'
  • search属性获取地址中携带的参数,符号?后面部分
    console.log(location.search)

  • hash属性获取地址的哈希值,符号#后面部分
    console.log(location.hash)

  • reload方法用来刷新当前页面,传入参数true时表示强制刷新

1
2
3
4
5
6
7
<button>点击刷新</button>
<script>
let btn = document.querySelector('button')
btn.addEventListener('click', function () {
location.reload(true) // 强制刷新
})
</script>

E. navigator对象

记录了浏览器自身的相关信息

  • userAgent检测浏览器的版本及平台

F. history对象

管理历史记录

history对象方法 作用
back() 可以后退功能
forward() 前进功能
go(参数) 前进后退功能 参数为1则前进一个页面 参数为-1则后退一个页面

41. 本地存储

A. 介绍

  • 在本地存储数据,存储在用户浏览器
  • 设置,读取方便,页面刷新也不丢失数据
  • 容量较大

B. localStorage

可以将数据永久存储在本地,除非手动删除,关闭页面也存在

1. 存储数据

localStorage.setItem(key,value)

2. 读取数据

localStorage.getItem(key)

3. 删除数据

localStorage.removeItem(key)

1
2
3
localStorage.setItem('uname','pink老师')
console.log(localStorage.getItem('uname'))
localStorage.removeItem('uname') //删除名字

C. sessionStorage

关闭浏览器窗口就会消失,用法和localStorage基本相同

D. 存储复杂数据类型

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

  • 存储:JSON.stringify(复杂数据类型)
  • 取出:JSON.parse(JSON字符串)
1
2
3
4
5
6
7
const obj = {
uname: 'abc',
age: 19,
gender: 'female'
}
localStorage.setItem('obj', JSON.stringify(obj)) //存储为JSON字符串
console.log(JSON.parse(localStorage.getItem('obj')))//把JSON字符串转换为对象取出

42. map()和join()

实现字符串拼接

  • map可以遍历数组处理数据,并返回新的数组
1
2
3
4
5
6
7
const arr = ['red', 'blue', 'green']
const newArr = arr.map(function (ele, index) {
console.log(ele) // 数组元素
console.log(index) // 数组索引号
return ele + '颜色'
})
console.log(newArr) //['red颜色','blue颜色','green颜色']
  • join()把数组中的所有元素转换为一个字符串
1
2
const arr = ['red颜色','blue颜色','green颜色'] 
console.log(arr.join('')) //red颜色blue颜色green颜色

43. 正则表达式

A. 介绍

用于匹配字符串中字符组合的模式

  • 表单验证(匹配)
  • 过滤敏感词(替换)
  • 字符串中提取我们想要的部分(提取)

B. 语法

1. 定义正则表达式语法

const 变量名 = /表达式/

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

test() 用于查看正则表达式与指定字符串是否匹配,返回true or false
语法: regObj.test(被检测的字符串)
例:

1
2
3
const str = '现在太阳下山了,太阳光要看不到了'
const reg = /太阳/
console.log(reg.test(str)) //返回true

C. 元字符

具有特殊意义的字符,例如26个英文字母abcdefg…表示为:[a-z]

1. 边界符(表示位置,开头结尾,必须用什么开头什么结尾)
边界符 说明
^ 表示匹配行首的文本(以谁开始)
$ 表示匹配行尾的文本(以谁结尾)
2. 量词(表示重复次数)
量词 说明
* 重复零次或更多次
+ 重复一次或更多次
? 重复零次或一次
{n} 重复n次
{n,} 重复n次或更多次
{n,m} 重复n到m次
3. 字符类(比如\d表示0~9)
  • []匹配字符集合
    只要包含[]中任何一个都返回true;如[abc]包含abc任何一个都为true
  • []里面加上-连字符
    使用连字符-表示一个范围;如[a-z]表示a到z26个字母
  • []里面加上^取反符号
    比如[^a-z]匹配除了小写字母以外的字符
  • .(点)匹配除换行符之外的任何单个字符
  • 预定义:某些常见模式的简写方式
预定类 说明
\d 匹配0-9之间任一数字
\D 匹配所有0-9以外的字符
\w 匹配任意的字母、数字和下划线
\W 匹配除所有字母、数字和下划线以外的字符
\s 匹配空格
\S 匹配非空格的字符

D. 修饰符

约束正则执行的细节问题,如是否区分大小写,是否支持多行匹配
语法: /表达式/修饰符

  • i是ignore的缩写,正则匹配时字母不区分大小写
  • g是global的缩写,匹配所有满足正则表达式的结果
  • 替换replace: 字符串.replace(/正则表达式/, '替换的文本')

44. 作用域

A. 局部作用域

1. 函数作用域

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

2. 块作用域

在JS中使用{}包裹的代码称为代码块,代码块中声明的变量外部有可能无法被访问

  • let和const声明的变量会产生块作用域,var不会产生块作用域

B. 全局作用域

全局作用域声明的变量,任何其他作用域都可以被访问

C. 作用域链

作用域链的本质是底层的变量查找机制

  • 函数执行时会优先查找当前函数作用域中查找变量
  • 如果当前作用域查找不到则会依次逐级查找父级作用域直到全局作用域

D. 垃圾回收机制

  • 内存的生命周期
    1. 内存分配
    2. 内存使用
    3. 内存回收
      全局变量一般不会回收,局部变量一般会被自动回收
  • 内存泄漏
    程序中分配的内存由于某种原因,程序未释放或无法释放叫内存泄漏
  • 回收算法-标记清除法
    从根部扫描对象,能查找到的就是使用的,查找不到就要回收

E. 闭包

闭包 = 内层函数 + 外层函数的变量
例:

1
2
3
4
5
6
7
8
function outer() {
const a = 1
function f() {
console.log(a)
}
f()
}
outer()
  • 闭包的作用: 外部也可以访问使用函数内部的变量

F. 变量提升

  • 仅存在于var声明变量
  • 把所有var声明的变量提升到当前作用域的最前面
  • 只提升声明,不提升赋值

45. 函数进阶

A. 函数提升

  • 会把所有函数声明提升到当前作用域最前面
  • 只提升函数声明,不提升函数调用
  • 函数先声明再调用

B. 函数参数

1. 动态参数

arguments是函数内部内置的伪数组变量,包含调用函数时传入的所有实参
例:求和函数,参数数量不限

1
2
3
4
5
6
7
8
9
function getSum() {
let sum = 0
for (let i = 0; i < arguments.length; i++) {
sum += arguments[i]
}
console.log(sum)
}
getSum(2, 3, 4)
getSum(1, 2, 3, 4, 2, 2, 3, 4)
2. 剩余参数(建议)

...获取的剩余实参,是个真数组

1
2
3
4
5
function getSum(a, b, ...arr) {
console.log(arr)
}
getSum(2, 3)
getSum(1, 2, 3, 4, 5)

C. 箭头函数

更适用于本来需要匿名函数的地方

1. 基本语法
  • 语法1:
1
2
3
4
const fn = function (){
console.log('普通函数')
}
fn()

改为:

1
2
3
4
const fn = () => {
console.log('箭头函数')
}
fn()
  • 语法2:只有一个参数可以省略小括号
1
2
3
4
const fn = function (x){
return x + x
}
console.log(fn(1))

改为:

1
2
3
4
const fn = x => {
return x + x
}
console.log(fn(1))
  • 语法3:如果函数体只有一行代码,可以写在一行上,无需写return直接返回值
1
2
3
4
const fn = function (x, y){
return x + y
}
console.log(fn(1, 2))

改为:

1
2
const fn = (x, y) => x + y
console.log(fn(1, 2))
  • 语法4:加括号的函数体返回对象字面量表达式
1
2
const fn1 = uname => ({ uname: uname})
console.log(fn1('fzh'))
2. 箭头函数参数

箭头函数没有arguments动态参数,但是有剩余函数…args
例:用箭头函数求和

1
2
3
4
5
6
7
8
9
const getSum = (...arr) => {
let sum = 0
for (let i = 0; i < arr.length; i++) {
sum += arr[i]
}
return sum
}
const result = getSum(2, 3)
console.log(result)
3. 箭头函数this

箭头函数不会创建自己的this,只会从自己的作用域链上一层沿用this

1
2
3
4
5
6
7
8
9
10
11
const user = {
name: '小明',
sleep: function () {
console.log(this) //指向 user
const fn = () => {
console.log(this) //指向user 该箭头函数中的this与sleep中的this一致
}
fn()
}
}
user.sleep()

46. 解构赋值

使用解构简洁的语法快速为变量赋值

A. 数组解构

将数组的单元值快速批量赋值给一系列变量的语法

  • 基本语法:
    1. 赋值运算符 = 左侧的[]用于批量声明变量,右侧数组的单元值将被赋值给左侧的变量
    2. 变量的顺序对应数组单元值的位置依次进行赋值操作

例:

1
2
3
4
5
const arr = [1, 2, 3]
const [a, b, c] = arr
console.log(a) // 1
console.log(b) // 2
console.log(c) // 3

B. 对象解构

将对象属性和方法快速批量赋值给一系列变量的语法

  • 对象属性的值和将被赋值与属性名相同的变量
1. 简单对象解构
1
2
3
4
5
6
7
const user = {
name: '小明',
age: 18
};
const {name, age} = user
console.log(name) // 小明
console.log(age) // 18
2. 数组对象解构
1
2
3
4
5
6
7
8
9
const pig = [
{
uname:'佩奇',
age: 6
}
]
const [{ uname, age }] = pig
console.log(uname)
console.log(age)
3. 多级对象解构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
const pig = {
name:'佩奇',
family: {
mother: '猪妈妈',
father: '猪爸爸’,
sister: '乔治'
},
age: 6
}
const { name, family: { mother, father, sister } } = pig
console.log(name)
console.log(mother)
console.log(father)
console.log(sister)

47. 遍历数组forEach方法

用于调用数组的每个元素,并将元素传递给回调函数
语法:

1
2
3
被遍历的数组.forEach(function(当前数组元素, 当前元素索引号){
//函数体
})

例:

1
2
3
4
const arr = ['pink', 'red', 'green' ]
arr.forEach(function (item, index) {
console.log(`当前数组元素是: ${item}`) //依次打印数组每一个元素
console.log(`当前数组元素的索引是: ${index}`) //依次打印数组每一个元素的索引

48. 深入对象

A. 创建对象三种方式

1. 利用对象字面量创建对象
1
2
3
const o = {
name: 'one'
}
2. 用new Object创建对象
1
2
const obj = new Object()
obj.uname = 'one'
3. 利用构造函数创建对象

B. 构造函数

构造函数主要用于初始化对象

  • 命名要以大写字母开头且只能由new来创建(约定)
    例:
1
2
3
4
5
6
7
8
9
10
function Pig(name, age, gender) {
this.name = name
this.age = age
this.gener = gender
}
const Peppa = new Pig('佩奇', 6, '女')// 创建佩奇对象
const George = new Pig('乔治', 3, '男')// 创建乔治对象
const Mum = new Pig('猪妈妈', 30, '女')// 创建猪妈妈对象
const Dad = new Pig('猪爸爸', 32, '男')// 创建猪爸爸对象
console.log(Peppa)//{name:'佩奇',age:6,gener:'女'}
  • 通过构造函数创建的对象称为实例对象,实例对象中的属性和方法称为实例成员(实例属性和实例方法)
  • 构造函数中的属性和方法称为静态成员(静态属性和静态方法)

49. 内置构造函数

A. Object

是内置的构造函数,创建普通对象

1. Object.keys静态方法获取对象中所有属性
1
2
3
4
const o = { name:'佩奇', age: 6}
const arr = Object.keys(o)
console.log(arr) // ['name', 'age']
console.log(Object.values(o)) //['佩奇', 6]
2. Object.assign静态方法用于对象拷贝
1
2
3
4
const o = { name: '佩奇', age: 6}
const obj = {}
Object.assign(obj, o)
console.log(obj) //{name:'佩奇',age:6}

B. Array

1. 数组的常见实例方法
方法 作用 说明
forEach 遍历数组 不返回数组,经常用于查找遍历数组元素
filter 过滤数组 返回新数组,返回的是筛选满足条件的数组元素
map 迭代数组 返回新数组,返回的是处理之后的数组元素,想要使用返回的新数组
reduce 累计器 返回累计处理的结果,经常用于求和等
join 拼接数组 将数组元素拼接为字符串,返回字符串
find 查找元素 查找元素,返回符合测试条件的第一个数组元素值,如果没有符合条件的则返回undefined
every 检测数组 检测数组所有元素是否都符合指定条件,如果所有元素都通过检测返回true,否则返回false
2. reduce方法

语法:
arr.reduce(function(){}, 起始值)
arr.reduce(function(上一次值, 当前值){}, 初始值)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const arr = [1, 5, 8]

// 1. 没有初始值
const total = arr.reduce(function (prev, current) {
return prev + current
})
console.log(total)

// 2. 有初始值
const total = arr.reduce(function (prev, current) {
return prev + current
}, 10)
console.log(total)

// 3. 箭头函数的写法
const total = arr.reduce((prev, current) => prev + current, 10)
console.log(total)

C. String

常见实例方法

实例方法 作用
length 用于获取字符串的长度
split(‘分隔符’) 将字符串拆分成数组
substring(需要截取的第一个字符的索引[,结束的索引号]) 用于字符串截取
startsWith(检测字符串[,检测位置索引号]) 检测是否以某字符开头

D. Number

用于创建数值
常用方法: toFixed()设置保留小数位的长度

1
2
const price = 12.345
console.log(price.toFixed(2)) //输出12.35

50. 编程思想

A. 面向过程编程

分析出解决问题所需的步骤,然后用函数把这些步骤依次解决

B. 面向对象编程

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

  • 面向对象的特性
    1. 封装性
    2. 继承性
    3. 多态性

51. 构造函数

  • 构造函数实现封装性,封装一个函数
  • 构造函数方法会存在内存浪费的问题

52. 原型

A. 介绍和prototype属性

构造函数通过原型分配实现方法共享
每个构造函数都有一个prototype属性,指向另一个对象

1
2
3
4
5
6
7
8
9
10
11
function Star(uname, age) {
this.uname = uname
this.age = age
}
console.log(Star.prototype)//返回一个对象称为原型对象
Star.prototype.sing = function () {
console.log('我会唱歌')
}
const ldh = new Star('刘德华',18)
const zxy= new Star('张学友',19)
console.log(ldh.sing === zxy.sing)// 结果是true 说明俩函数一样,共享

B. constructor属性

每个原型对象里面都有个constructor属性
该属性指向该原型对象的构造函数

1
2
3
4
5
6
7
8
9
10
function Star(name) {
this.name = name
}
Star.prototype = {
constructor: Star,//手动利用constructor指回Star构造函数
sing: function () { console.log('唱') },
dance: function () { console.log('跳') },
rap: function () { console.log('rap') }
}
console.log(Star.prototype.constructor) //指向Star

C. 对象原型

对象都有一个属性_proto_指向构造函数的prototype原型对象

D. 原型继承

JS大多借助原型对象实现继承的特性

E. 原型链

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

53. 深浅拷贝

浅拷贝和深拷贝只针对引用类型

A. 浅拷贝

  • 拷贝的是地址
  • 如果是单层对象没问题,如果有多层就有问题
    常见方法:
  1. 拷贝对象:Object.assgin()展开运算符{...obj}
  2. 拷贝数组:Array.prototype.concat()[...arr]

B. 深拷贝

拷贝的是对象,不是地址
常见方法:

  1. 通过递归实现深拷贝
  2. lodash/cloneDeep
  3. 通过JSON.stringify()

54. 异常处理

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

A. throw抛异常

1
2
3
4
5
6
7
8
function counter(x, y) {
if (!x || !y) {
// throw '参数不能为空!';
throw new Error('参数不能为空!')
}
return x + y
}
counter()

B. try/catch捕获异常

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<p>123</p>
<script>
function fn() {
try {
// 可能发送错误的代码 要写到 try
const p = document.querySelector('.p')
p.style.color = 'red'
} catch (err) {
// 拦截错误,提示浏览器提供的错误信息,但是不中断程序的执行
console.log(err.message)
throw new Error('你看看,选择器错误了吧')
return // 需要加return 中断程序
}
finally {
alert('弹出对话框')// 不管你程序对不对,一定会执行的代码
}
console.log(11)
}
fn()
</script>

C. debugger

55. 处理this

A. this指向

1. 普通函数this指向

谁调用我,我指向谁

2. 箭头函数this指向
  • 箭头函数中并不存在this
  • 箭头函数中的this引用就是最近作用域的this
  • 向外层作用域,一层一层查找this,直到有this定义

B. 改变this

1. call()

使用call方法调用函数,同时指定被调用函数中this的值
语法: fun.call(thisArg,arg1,arg2,...)

2. apply()

语法: fun.apply(thisArg,[argsArray])

  • thisArg: 在fun函数运行时指定的this值
  • argsArray: 传递的值,必须包含在数组里面
3. bind()(重要)

bind()不会调用函数,但是能改变函数内部this指向
语法: fun.bind(thisArg,arg1,arg2,...)

1
2
3
4
5
6
7
8
9
function sayHi() {
console.log(this)
}
let user = {
name: '小明',
age: 18
}
let sayHello = sayHi.bind(user); //用 bind 指定 this 的值
sayHello()//调用使用 bind 创建的新函数

56. 性能优化

  • 防抖:单位时间内,频繁触发事件,只执行最后一次
  • 节流:单位时间内,频繁触发事件,只执行一次