环境对象this
环境对象本质上是一个关键字 this
this所在的代码区域不同,代表的含义不同
全局作用域中的this
全局作用域中this代表window对象
局部作用域中的this
在局部作用域中(函数中)this代表window对象
原因是函数调用的时候简写了,函数完整写法window.函数()
事件局部作用域中的this
事件中的this指向事件源
<input type="button">
<script>
console.log(this)
function fn() {
console.log('函数中this')
console.log(this)
}
fn()
let btn = document.querySelector('input')
btn.addEventListener('click', function () {
console.log(this)
})
</script>
规律:哪个对象在调用这个方法,那么方法中的this就指向当前调用对象(谁调用就指向谁)
let obj = {
name: '老段',
eat: function () {
console.log(this)
}
}
obj.eat()
回调函数
回调函数:本质是一个函数:如果我们将一个函数作为参数,当前这个函数就叫回调函数
高阶函数:还是一个函数,如果一个函数的参数是函数,那么这个函数就是高阶函数
事件
事件流
事件流就是事件的一种现象
事件流:事件冒泡现象,事件捕获现象
事件冒泡现象
1.在嵌套结构中,如果子元素事件会向外(父元素)传递,这个现象就叫事件冒泡现象
在嵌套结构中子元素向父元素传递
2.解决:如果遇到事件冒泡,而且冒泡对我们的程序产生了影响,我们可以阻止冒泡
阻止事件冒泡的时候,一定要给子元素阻止,阻止事件冒泡的语法:事件对象参数.stopPropagation();
点击子元素:
<div class="one">
<div class="two"></div>
</div>
<script>
// 需求,点击两个盒子,分别输出一句话
let one = document.querySelector('.one')
let two = document.querySelector('.two')
// 点击第一个盒子
one.addEventListener('click', function () {
console.log('我是父元素')
})
two.addEventListener('click', function () {
console.log('我是子元素')
})
</script>
事件捕获
现象:和事件冒泡相反,在嵌套结构中,事件从父元素向子元素传递
注意:
1.事件程序中默认看不到事件捕获
2.如果要看到事件捕获,要求必需要用addEventListener注册事件,并且设置一个参数为true
事件捕获不用管,因为默认是事件冒泡
<div class="one">
<div class="two"></div>
</div>
<script>
// 需求,点击两个盒子,分别输出一句话
let one = document.querySelector('.one')
let two = document.querySelector('.two')
// 点击第一个盒子
one.addEventListener('click', function () {
console.log('我是父元素')
}, true);
two.addEventListener('click', function () {
console.log('我是子元素')
}, true)
</script>
点击子元素,先显示父元素
解绑事件
通过解绑事件,可以不执行事件中的代码
<input type="button" value="按钮">
<div></div>
<script>
let btn = document.querySelector('input')
function fn() {
console.log('123')
}
// 函数带括号则立刻执行
btn.addEventListener('click', fn);
// 解绑事件
// a)如果注册事件通过addEventListener方式注册的,那么移除事件(解绑)通过
// removeEventListener('事件类型',函数名)移除
// 移除btn
btn.removeEventListener('click', fn)
// b)如果元素注册事件的时候,通过on方式注册的,那么解绑事件的时候
// 通过语法:DOM对象.on事件类型=null
// 总结 console.log(btn);输出的结构是以html标签的形式输出的
// console.dir(btn)输出的结构是以对象格式输出的
</script>
事件委托(★)
在注册事件的时候可以减少代码量
<div>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
</div>
<script>
// 事件委托的实现步骤
// 1.必须将事件给父元素注册(无所谓直接父元素还是间接父元素)
// 2.必须找到真正的事件源(对应的标签对象),可以进行各种处理:事件对象参数.target
// 要求:点击每一个li标签,输出li标签的内容
// 不用事件委托实现
// let lis = document.querySelectorAll('li')
// for (let i = 0; i < lis.length; i++) {
// lis[i].addEventListener('click', function () {
// console.log(this.innerHTML)
// })
// }
// 事件委托实现
let div = document.querySelector('div')
div.addEventListener('click', function (e) {
// 获得真正的事件源
let li = e.target
// 获取事件源内容
console.log(li.innerHTML)
})
</script>
其他事件
页面加载事件:load
当页面中所有资源都加载完成之后,自动触发load事件
写法:window.addEventListener(‘load’,function(){})
应用场景:如果将获取标签的代码写到html结构(body)的前面,则必须加load事件
为什么获取标签的代码写到html结构前面必须加load事件才可以?
a)js的执行顺序是按照从上到下执行的
b)如何获取标签的代码写到head中,页面中还没有标签对象,会报错
页面加载事件:DOMContentLoaded
作用:当我们整个HTML文档加载完成后就会执行DOMContentLoaded事件
当初始的HTML文档被加载完成和解析完成之后,DOMContentLoaded事件被触发,而无需等待样式表、图像等完全加载
语法:document.addEventListener(‘DOMContentLoaded’,function(){})
页面滚动事件:scroll
语法:window.addEventListener(‘scroll’,function(){})
应用场景:拖拽滚动条,页面出现固定定位的导航
获取滚动距离
<script>
// 获取滚动距离
// 对象.scrollLeft 获取水平方向的滚动距离
// 对象.scrollTop 获取垂直方向的滚动距离
// 备注:1.获取滚动距离需要在滚动事件中获取
// 2.如果给window注册滚动事件并获取滚动距离,不能通过window.scrollTop获取
// 3,如果给window注册滚动事件并获取滚动距离,通过document.documentElement.scrollTop获取
//4.获取到的滚动距离由两部分组成:
window.addEventListener('scroll', function () {
let lg = document.documentElement.scrollTop
console.log(lg)
})
</script>