1. document对象
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>document对象</title>
</head>
<body>
<script>
/*
document对象:
- 表示的是整个网页
- 原型链:
HTMLDocument -> Document -> Node -> EventTarget -> Object.prototype -> null
- 部分属性:
- document.documentElement html根元素
- document.head head元素
- document.title title元素
- document.body body元素
- document.links 页面中的所有超链接
......
- mdn文档:https://developer.mozilla.org/en-US/docs/Web/API/Document
*/
</script>
</body>
</html>
2. 元素节点
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>元素节点</title>
</head>
<body>
<script>
/*
元素节点:
- 在网页中,每一个标签都是一个元素节点
- 如何获取元素节点对象?
1. 通过document对象获取
2. 通过document对象创建
- 通过document来获取已有的元素节点:
- document.getElementById():
- 根据id获取一个
- document.getElementsByClassName():
- 根据元素的class属性值获取一组元素节点对象
- 返回的是一个类数组对象,不是数组
- 返回结果是实时更新的(即当网页中添加了新的元素,返回结果也会同步实时更新)
- document.getElementsByTagName():
- 根据标签名获取一组元素节点对象
- 同理getElementsByClassName()方法
- document.getElementsByTagName("*") 获取网页中的所有元素节点对象
- document.getElementsByName():
- 根据name属性获取一组元素节点对象
- 同理getElementsByClassName()方法
- 常用于获取 form 表单中的元素节点对象
- document.querySelectorAll():
- 根据选择器获取元素节点对象
- 返回结果是一个类数组对象(不会实时更新)
- document.querySelector():
- 根据选择器获取网页中第一个符合条件的元素节点对象
- 创建元素节点对象:
- document.createElement():
- 根据标签名创建元素节点对象
- const div = document.createElement('div')
*/
</script>
</body>
</html>
3. 元素的属性和方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>元素的属性和方法</title>
</head>
<body>
<script>
/*
通过元素节点对象获取其他节点的方法:
- element.childNodes 获取当前元素的子节点(包含空白的子节点,文本,换行符等等)
- element.children 获取当前元素的子元素
- element.firstElementChild 获取当前元素的第一个子元素
- element.lastElementChild 获取当前元素的最后一个子元素
- element.nextElementSibling 获取当前元素的下一个兄弟元素
- element.previousElementSibling 获取当前元素的前一个兄弟元素
- element.parentNode 获取当前元素的父节点
- element.tagName 获取当前元素的标签名
*/
</script>
</body>
</html>
4. 文本节点
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>文本节点</title>
</head>
<body>
<script>
/*
网页中的所有文本内容都是文本节点对象
- element.textContent 获取或修改元素的文本内容
- 获取的是标签中的原始内容,不考虑css样式
- element.innerText 获取或修改元素的文本内容
- 当修改的内容中包含html元素时,会自动进行转义
- 获取内容时,会考虑css的样式(展示什么获取的就是什么)
- 读取css样式时,会触发网页的重排(计算css样式)
- element.innerHtml 获取或修改元素中的html代码
- 插入内容时,有xss注入风险
*/
</script>
</body>
</html>
5. 属性节点
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>属性节点</title>
</head>
<body>
<input id="aaaa" class="aaa" type="text" name="username" value="admin"/>
<script>
/*
属性节点(Attr):
- 如何操作属性节点:
方式一:
- 读取:元素.属性名(注:class属性需要使用calssName来读取)
- 修改:元素.属性名 = 属性值
方式二:
- 读取:元素.getAttribute(属性名)
- 修改:元素.setAttribute(属性名, 属性值)
- 删除:元素.removeAttribute(属性名)
*/
const input = document.querySelector("[name=username]")
console.log('input.type:', input.type)
console.log('input.id:', input.id)
console.log('input.class:', input.className)
console.log('input.name:', input.name)
console.log('input.value:', input.value)
//input.value = '孙笑川'
console.log('---------------------------------------');
console.log('input.getAttribute(\'type\'):', input.getAttribute('type'))
console.log('input.getAttribute(\'id\'):', input.getAttribute('id'))
console.log('input.getAttribute(\'class\'):', input.getAttribute('class'))
console.log('input.getAttribute(\'name\'):', input.getAttribute('name'))
console.log('input.getAttribute(\'value\'):', input.getAttribute('value'))
input.setAttribute('value', '药水哥')
input.setAttribute('disabled', true)
input.removeAttribute('disabled')
</script>
</body>
</html>
6. 事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>事件</title>
</head>
<body>
<!-- <button id="btn" onclick="alert('直接在元素的属性中设置')">点一下</button> -->
<button id="btn">点一下</button>
<script>
/*
事件(Event):
- 用户与网页之间发生的交互行为
- 可以通过为事件绑定响应函数,来完成与用户之间的交互
- 绑定方式:
1. 直接在元素的属性中设置
2. 为元素的指定属性设置回调函数来绑定(一个事件只能绑定一个响应函数,后来者居上)
3. 通过元素的 addEventListener() 方法来绑定(可以重复绑定,先绑定的谁,谁先执行)
*/
const btn = document.getElementById('btn')
//btn.onclick = function() {
// alert('为元素的指定属性设置回调函数来绑定')
//}
btn.addEventListener("click", function() {
alert('通过元素的 addEventListener() 方法来绑定')
})
</script>
</body>
</html>
7. 文档的加载
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>文档的加载</title>
<script>
// 方式二
//window.onload = function() {
// const btn = document.getElementById('btn')
// console.log(btn)
//}
//window.addEventListener('load', function() {
// const btn = document.getElementById('btn')
// console.log(btn)
//})
// 方式三
//document.addEventListener('DOMContentLoaded', function() {
// const btn = document.getElementById('btn')
// console.log(btn)
//})
</script>
<script defer src="./script/index.js"></script>
</head>
<body>
<button id="btn">点一下</button>
<script>
/*
网页是自上而下加载的,如果将js代码编写到网页的上边(之前),js代码在执行时,网页还没有加载完毕,这时会出现无法获取DOM的情况
解决方案:
1. 将 script 标签放到 body 之后
- 所有方式中优先级最高
2. 将js代码写到 window.onload 的回调函数中
- 网页中所有的文档加载完后才执行
3. 将js代码写到 document 对象的 DOMContentLoaded 的回调函数中
- 当前文档加载完毕之后触发(相比方式二执行时机更早)
4. 将代码编写到外部的js文件中,然后以defer的形式引入
- 相比方式三执行时机更早
*/
// 方式一
//const btn = document.getElementById('btn')
//console.log(btn)
</script>
</body>
</html>
index.js
const btn = document.getElementById('btn')
console.log(btn)
8. DOM的修改
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>DOM的修改</title>
</head>
<body>
<button id="btn1">添加元素</button>
<button id="btn2">删除元素</button>
<button id="btn3">替换元素</button>
<ul id="list">
<li id="sxc">孙笑川</li>
<li id="ysg">药水哥</li>
</ul>
<script>
const list = document.getElementById('list')
const btn1 = document.getElementById('btn1')
btn1.onclick = function() {
// 创建新的li
const li = document.createElement('li')
li.innerText = 'Giao哥'
li.id = 'gg'
// appendChild() 给节点添加子节点
//list.appendChild(li)
/*
insertAdjacentElement():
- 像元素的指定位置添加元素
- 参数:
1. 要添加的位置:
- beforeend 标签的最后
- afterbegin 标签的开始
- beforebegin 在当前元素的前边插入(即插入兄弟元素)
- afterend 在当前元素的后边插入(即插入兄弟元素)
2. 要添加的元素
*/
//list.insertAdjacentElement('beforeend', li)
// 同理 insertAdjacentElement() 方法
list.insertAdjacentHTML('beforeend', '<li id="gg">Giao哥</>')
}
const btn2 = document.getElementById('btn2')
btn2.onclick = function() {
const sxc = document.getElementById('sxc')
sxc.remove()
}
const btn3 = document.getElementById('btn3')
btn3.onclick = function() {
const sxc = document.getElementById('sxc')
const li = document.createElement('li')
li.innerText = 'Giao哥'
li.id = 'gg'
sxc.replaceWith(li)
}
</script>
</body>
</html>
9. XSS注入问题
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>XSS注入问题</title>
</head>
<body>
<script>
/*
在涉及到需要将用户输入的内容插入到网页中时,
尽量使用 元素.innerText 或 元素.textContent 方法代替 元素.innerHTML 方法
前两种方法在赋值时会进行转义
*/
</script>
</body>
</html>
10. 节点的复制
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>节点的复制</title>
</head>
<body>
<button id="btn">复制节点</button>
<ul id="list1">
<li id="l1">孙笑川</li>
<li id="l2">药水哥</li>
<li id="l3">Giao哥</li>
</ul>
<ul id="list2">
<li>刘波</li>
</ul>
<script>
// 点击按钮后,复制list1的节点到list2
const list1 = document.getElementById('list1')
const list2 = document.getElementById('list2')
const l1 = document.getElementById('l1')
const btn = document.getElementById('btn')
btn.onclick = function() {
/*
cloneNode() 方法:
- 参数:
- false(默认值) 复制节点的所有属性,但不包括子节点
- true 复制所有信息,包括子节点
*/
const newL1 = l1.cloneNode(true)
newL1.id = 'newL1'
list2.appendChild(newL1)
}
</script>
</body>
</html>
11. 修改css样式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>修改css样式</title>
<style>
.box1 {
width: 200px;
height: 200px;
background-color: lightblue;
}
.box2 {
width: 300px;
height: 300px;
border: 1px black solid;
background-color: lightgreen;
}
</style>
</head>
<body>
<button id="btn">修改样式</button>
<hr/>
<div class="box1"></div>
<script>
// 点击按钮后修改box1的样式
const box1 = document.getElementsByClassName('box1')[0]
const btn = document.getElementById('btn')
// 直接修改样式(不建议直接使用)
// btn.onclick = function() {
// // 修改宽度
// // 元素.style.样式名(小驼峰) = 样式值
// box1.style.width = '300px'
// box1.style.backgroundColor = 'lightgreen'
// }
// 通过class属性间接修改样式
btn.onclick = function() {
// 不建议这么操作
// box1.className += ' box2'
/*
元素.classList:
- 是一个对象,提供了对当前元素的 class 的各种操作方法
- 常用方法:
- add(): 向元素中添加一个或多个 class
- remove(): 移除指定 class
- toggle(): 切换元素的class(一次只能操作一个)
- replace(): 替换 class
- contains(): 检查是否包含指定 class
*/
// box1.classList.add('box2', 'box3')
// box1.classList.remove('box2')
// box1.classList.toggle('box2')
// box1.classList.replace('box1', 'box2')
console.log(box1.classList.contains('box1'))
}
</script>
</body>
</html>
12. 读取css样式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>读取css样式</title>
<style>
.box1 {
width: 200px;
height: 200px;
background-color: lightblue;
}
.box1::before {
color: blueviolet;
content: '测试';
}
</style>
</head>
<body>
<button id="btn">读取样式</button>
<hr/>
<div class="box1"></div>
<script>
// 点击按钮后读取css样式
const box1 = document.getElementsByClassName('box1')[0]
const btn = document.getElementById('btn')
btn.onclick = function() {
/*
getComputedStyle():
- 读取指定元素所有生效的样式,以对象的形式返回
- 参数:
1. 要获取样式的对象
2. 要获取的伪元素
- 注:样式对象中返回的值不一定能直接拿来计算,
有可能是 auto 等等
*/
const styleObj = getComputedStyle(box1)
console.log(styleObj)
const box1Before = getComputedStyle(box1, '::before')
console.log(box1Before.content)
}
</script>
</body>
</html>
13. 通过属性读取样式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>通过属性读取样式</title>
<style>
.box1 {
width: 200px;
height: 200px;
background-color: lightblue;
margin: 50px;
padding: 50px;
border: 2px black solid;
overflow: auto;
}
.box2 {
width: 100px;
height: 500px;
background-color: lightcoral;
}
</style>
</head>
<body>
<button id="btn">读取样式</button>
<hr/>
<div id="box1" class="box1">
<div id="box2" class="box2"></div>
</div>
<script>
const btn = document.getElementById('btn')
const box1 = document.getElementById('box1')
btn.onclick = function() {
/*
获取元素内部的高度和宽度(包括内容区和内边距):
元素.clientWidth
元素.clientHeight
获取元素的可见框的大小(包括内容区,内/外边距):
元素.offsetHeight
元素.offsetWidthyuan
获取元素滚动区域的大小:
元素.scrollHeight
元素.scrollWidth
获取元素的定位父元素:
元素.offsetParent
注:定位父元素:离当前元素最近的开启了定位的祖先元素,如果都没有开启,则返回body
获取元素相对于其定位父元素的偏移量:
元素.offsetTop
元素.offsetLeft
获取元素滚动条的偏移量:
元素.scrollTop
元素.scrollLeft
*/
console.log(box1.scrollTop)
console.log(box1.scrollLeft)
}
</script>
</body>
</html>
14. 事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>事件</title>
<style>
.box1 {
width: 300px;
height: 300px;
background-color: lightblue;
border: 1px black solid;
}
</style>
</head>
<body>
<div id="box1" class="box1"></div>
<script>
/*
事件(Event):
- 浏览器在事件触发时所创建的对象
- 如:鼠标的坐标、键盘的按键等等
- 浏览器在创建事件对象后,会将其作为响应函数的参数传递
可以在事件的回调函数中定义一个形参来接收事件对象
*/
const box1 = document.getElementById('box1')
// box1.onmousemove = function(event) {
// console.log(event)
// }
// box1.onmousemove = event => {
// console.log(event)
// }
// box1.addEventListener('mousemove', function() {
// console.log(event)
// })
box1.addEventListener('mousemove', event => {
console.log(event)
})
</script>
</body>
</html>
15.事件对象
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>事件对象</title>
<style>
.box1 {
width: 300px;
height: 300px;
background-color: lightblue;
border: 1px black solid;
}
.box2 {
width: 150px;
height: 150px;
background-color: lightcoral;
border: 1px black solid;
}
.box3 {
width: 75px;
height: 75px;
background-color: lightseagreen;
border: 1px black solid;
}
</style>
</head>
<body>
<div id="box1" class="box1">
<div id="box2" class="box2">
<div id="box3" class="box3"></div>
</div>
</div>
<a id="test" href="https://www.bing.com" target="_blank">点击跳转</a>
<script>
/*
DOM中有多种不同类型的事件对象:
- 共同祖先 Event:
- event.target 表示触发事件的对象
- event.currentTarget 绑定事件的对象(与this同理)
- event.stopPropagation() 停止事件的传递
- event.preventDefault() 取消事件的默认行为(推荐使用)
- 事件的冒泡(bubble):
- 指事件的向上传递
- 当元素上的某个事件被触发后,其祖先元素上的相同的事件也被同时触发
*/
const box1 = document.getElementById('box1')
box1.onclick = event => {
console.log('box1', event.target)
alert('box1')
}
const box2 = document.getElementById('box2')
box2.onclick = event => {
console.log('box2', event.target)
alert('box2')
}
const box3 = document.getElementById('box3')
box3.onclick = event => {
console.log('box3', event.target)
// 停止冒泡事件
event.stopPropagation()
alert('box2')
}
const test = document.getElementById('test')
test.addEventListener('click', event => {
// 取消事件的默认行为
event.preventDefault()
alert('点击后不进行超链接跳转')
})
</script>
</body>
</html>
16. 事件的冒泡
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>事件的冒泡</title>
<style>
.box1 {
width: 75px;
height: 75px;
background-color: lightblue;
border-radius: 50%;
position: absolute;
}
.box2 {
width: 300px;
height: 300px;
background-color: lightcoral;
}
.box3 {
width: 200px;
height: 200px;
background-color: lightgreen;
}
.box4 {
width: 150px;
height: 150px;
background-color: lightgray;
position: absolute;
bottom: 0;
}
</style>
</head>
<body>
<div id="box1" class="box1"></div>
<div id="box2" class="box2"></div>
<div id="box3" class="box3" onclick="alert('box3')">
<div id="box4" class="box4" onclick="alert('box4')"></div>
</div>
<script>
// 使box1跟随鼠标移动
document.addEventListener("mousemove", (event) => {
box1.style.left = event.x + "px"
box1.style.top = event.y + "px"
})
const box2 = document.getElementById("box2")
box2.addEventListener("mousemove", (event) => {
event.stopPropagation()
})
// 点击box4依然会触发事件冒泡,弹出box3,即事件的冒泡与元素的样式无关,只与结构有关
</script>
</body>
</html>
17. 事件委派
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>事件委派</title>
</head>
<body>
<button id="btn">添加</button>
<ul id="list">
<li><a href="javascript:;">链接一</a></li>
<li><a href="javascript:;">链接二</a></li>
<li><a href="javascript:;">链接三</a></li>
<li><a href="javascript:;">链接四</a></li>
</ul>
<script>
const links = document.getElementsByTagName("a")
// for (let i = 0; i < links.length; i++) {
// links[i].addEventListener('click', event => {
// alert(links[i].textContent)
// })
// }
const list = document.getElementById("list")
const btn = document.getElementById("btn")
btn.addEventListener("click", () => {
list.insertAdjacentHTML("beforeend", `<li><a href="javascript:;">链接${Math.ceil(Math.random() * 10)}</a></li>`)
})
//需求:只进行一次事件绑定,即可让所有的超链接(不管是原有的还是新添加的)都具有指定的事件
document.addEventListener("click", (event) => {
if ([...links].includes(event.target)) {
alert(event.target.textContent)
}
})
/*
事件委派:
- 将原本绑定给多个元素的事件,统一绑定给document(此处以绑定给document为例,绑定的对象随业务场景的不同而不同)
- 降低代码的复杂度
*/
</script>
</body>
</html>
18. 事件的捕获
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>事件的捕获</title>
<style>
.box1 {
width: 300px;
height: 300px;
background-color: lightblue;
}
.box2 {
width: 200px;
height: 200px;
background-color: lightcoral;
}
.box3 {
width: 100px;
height: 100px;
background-color: lightgrey;
}
</style>
</head>
<body>
<div id="box1" class="box1">
<div id="box2" class="box2">
<div id="box3" class="box3"></div>
</div>
</div>
<script>
/*
事件的传播机制:
- 在DOM中,分为三个阶段:
1. 捕获阶段(由祖先元素向目标元素进行事件的捕获)
2. 目标阶段(触发事件的对象)
3. 冒泡阶段(由目标元素向祖先元素进行事件的冒泡)
- 默认情况下是在冒泡阶段触发事件
- 事件的捕获:
- 指事件从外向内的传导
- document -> html -> body -> 具体元素
- 默认情况下,事件不会再捕获阶段触发
- 可以通过设置 元素.addEventListener() 方法的第三个参数为true来在捕获阶段触发事件(一般不这么使用)
*/
const box1 = document.getElementById('box1')
const box2 = document.getElementById('box2')
const box3 = document.getElementById('box3')
// 通过设置第三个参数为true,在捕获阶段触发点击事件
// 此时 alert 的顺序为:box1 -> box2 -> box3
// 一般情况下不会这么使用
box1.addEventListener('click', event => {
alert('box1 - ' + event.eventPhase)
// event.eventPhase 事件触发的阶段
// 1:捕获阶段 2:目标阶段 3:冒泡阶段
}, true)
box2.addEventListener('click', event => {
alert('box2 - ' + event.eventPhase)
}, true)
box3.addEventListener('click', event => {
alert('box3 - ' + event.eventPhase)
}, true)
</script>
</body>
</html>
19. BOM对象
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>BOM对象</title>
</head>
<body>
<script>
/*
BOM:
- 浏览器对象模型
- 通过BOM对象,可以完成对浏览器的各种操作
- 五个BOM对象:
- Window:浏览器窗口(全局对象)
- Navigator:浏览器的对象
- Location:浏览器的地址栏信息
- History:浏览器的历史记录(控制浏览器的前进后退)
- Screen:屏幕信息
*/
</script>
</body>
</html>
20. Navigator
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Navigator</title>
</head>
<body>
<script>
/*
Navigator(浏览器的对象):
- mdn文档:https://developer.mozilla.org/en-US/docs/Web/API/Navigator
*/
console.log(navigator.userAgent)
</script>
</body>
</html>
21. Location
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Location</title>
</head>
<body>
<button id="btn">点一下</button>
<script>
/*
Location(浏览器的地址栏信息):
- mdn文档:https://developer.mozilla.org/en-US/docs/Web/API/Location
*/
const btn = document.getElementById('btn')
btn.addEventListener('click', () => {
// 可以直接给location赋值,表示跳转到指定地址
// location = 'https://www.bing.com'
// 等价于直接赋值
//location.assign('https://www.bing.com')
// 执行替换之后不能通过历史记录回退
//location.replace('https://www.bing.com')
// 刷新页面
// location.reload()
// 强制清缓存刷新 Ctrl + F5
location.reload(true)
})
</script>
</body>
</html>
22. History
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>History</title>
</head>
<body>
<button id="btn">点一下</button>
<script>
/*
History(浏览器的历史记录):
- mdn文档:https://developer.mozilla.org/en-US/docs/Web/API/History
*/
const btn = document.getElementById('btn')
btn.addEventListener('click', () => {
// 后退
// history.back()
// 前进
// history.forward()
// 1:前进1,-1:后退1
history.go(1)
})
console.log('历史记录的数量:', history.length)
</script>
</body>
</html>
23. 定时器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>定时器</title>
</head>
<body>
<div id="num"></div>
<script>
/*
定时器:
- 让代码在指定时间后执行
- 设置方式:
1. setTimeout():
- 参数:
1. 回调函数
2. 延迟的时间(单位毫秒)
- 关闭定时器:
- clearTimeout()
2. setInterval():
- 每间隔一段时间,代码就执行一次
- 参数:
1. 回调函数
2. 延迟的时间(单位毫秒)
- 关闭定时器:
- clearInterval()
*/
const timer = setTimeout(() => {
alert('延迟1.5s再执行')
}, 1500)
// 关闭定时器
clearTimeout(timer)
const timer1 = setInterval(() => {
alert('延迟2s再执行')
}, 2000)
clearInterval(timer1)
// const num = document.getElementById('num')
// let index = 0
// setInterval(() => {
// index ++
// num.textContent = index
// }, 2000)
/*
定时器的本质,即在指定时间后将函数添加到消息队列中
注:函数实际的执行时间要看调用栈的情况
*/
// console.time()
// setTimeout(() => {
// console.timeEnd()
// console.log('setTimeout()定时器执行了...')
// // 打印结果为:
// // default: 5003.26904296875 ms
// // 定时器执行了...
// }, 3000)
// const begin = Date.now()
// while (Date.now() - begin < 5000) {}
/*
setInterval()方法每隔一段时间就将函数添加到消息队列中,
但函数执行的间隔时间受函数自身执行速度的影响,所以每次的间隔时间不一定是定时器中指定的间隔时间
*/
// console.time()
// setInterval(() => {
// console.timeEnd()
// console.log('setInterval()定时器执行了...')
// alert('setInterval()')
// console.time()
// }, 3000)
// 需求:确保函数每一次执行的间隔时间都相同
// console.time()
// setTimeout(function test() {
// console.timeEnd()
// console.log('确保函数每一次执行的间隔时间都相同')
// console.time()
// setTimeout(test, 3000)
// }, 3000)
// 打印结果为 222 \n 111
// console.log(222)在主调用栈中,优先级最高
// console.log(111)是在定时器等待0ms后将函数投递到消息队列中
setTimeout(() => {
console.log(111)
}, 0)
console.log(222)
</script>
</body>
</html>
24. 事件循环
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>事件循环</title>
</head>
<body>
<button id="btn">点一下</button>
<button id="btn1">消息队列测试</button>
<script>
/*
事件循环(Event Loop):
- 函数在每次执行时,都会产生一个执行环境
- 执行环境负责存储函数执行时产生的一切数据
调用栈(Call Stack):
- 后进先出(后来者居上)
- 负责存储函数的执行环境
- 当一个函数被调用时,它的执行环境会作为一个栈帧,
插入到调用栈的栈顶,执行完之后改栈帧会自动弹出
消息队列:
- 先进先出
- 负责存储将要执行的函数
- 当触发一个事件时,其执行函数并不是直接添加到调用栈中
即:事件触发后,js引擎将事件响应函数插入到消息队列中排队
*/
function test() {
console.log('执行test函数')
function test1() {
console.log('执行test1函数')
}
console.log('test执行完毕')
}
// test()
const btn = document.getElementById('btn')
btn.addEventListener('click', () => {
alert('btn按钮')
const begin = Date.now()
while (Date.now() - begin < 3000) {}
})
const btn1 = document.getElementById('btn1')
btn1.addEventListener('click', () => {
alert('btn1按钮')
})
</script>
</body>
</html>
评论 (0)