一.事件委托
减少内存消耗 避免多次循环
例子:对外层ul进行事件绑定 从而避免进行循环 实现点击出现li的文本
<ul id="list">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<button class="btn">添加</button>
<script>
var oList = document.getElementById('list');
var oBtn = document.getElementsByClassName('btn')[0];
var oLists = document.querySelectorAll('#list li');
// 事件委托
oList.onclick = function (event) {
if (event.target.tagName == 'LI') {
console.log(event.target.innerHTML);
}
}
event 事件源 判断event.target.tagName是否为LI即可进行事件操作
二.this指向
1.点击事件 this指向对象本身
box.onclick = function(){
console.log(this);
}
指向box标签
2.函数调用 this指向window
function show(){
console.log(this);
}
show();
指向window
3.对象方法 this指向对象本身
let obj={
name:'who',
show:function(){
console.log(this);
}
}
obj.show();
指向obj
4.定时器 默认指向window 如果外层有函数 this指向上一层
setInterval(function() {
console.log(this)
},1000)
指向window
box.onclick = function() {
// setInterval(()=>{
// console.log(this)
// },2000)
// }
指向box 标签
三.改变this指向
1.call
fn1.call(obj,2,3)
2.apply
fn1.apply(obj,[2,3])
3.bind
fn1.bind(obj, 2, 3)();
4.三者区别
* 1.bind无法直接调用 call和apply可以直接调用
* 2.call和bind从第二项开始,要传入的参数是逐个传入的
* 3.apply从第二项开始,要传入的参数在数组中逐个传入
四.原型与原型链※
1.构造函数
* 1.首字母大写
* 2.使用时 通过new去进行实例化
* 3.this执行当前函数本身
* 4.反出值 不用return
* 属性 写在构造函数下
* 方法 写在原型下
2.原型
1.构造函数中自带了constructor(构造器)和prototype(原型对象/显性方法)
2.实例对象中自带了_proto_方法 指向当前对象原型
3.prototype 与 _proto_ 等价的
4.constructor指向的是prototype的构造函数


3.原型链
访问对象属性时 先从对象本身属性上寻找
然后通过 _proto_ 去原型上寻找
若还没找到 则在原型对象prototypes上寻找 找到就返回 未找到(undefined)/null
4.总结⭐
面试题
所有的函数数据类型都天生自带一个prototype属性,该属性的属性值是一个对象,指向原型
prototype的属性值中天生自带一个constructor属性,其constructor属性值指向当前原型所属的构造函数/类
所有的对象数据类型(实例),都天生自带一个_proto_属性,该属性的属性值指向当前实例所属类的原型
总结
1.把所有的对象共用的属性全部放在堆内存的一个对象(共用属性组成的对象),然后让每一个对象的 __proto__存储这个「共用属性组成的对象」的地址。
而这个共用属性就是原型,原型出现的目的就是为了减少不必要的内存消耗。
2.原型链就是对象通过__proto__向当前实例所属类的原型上查找属性或方法的机制,如果找到Object的原型上还是没有找到想要的属性或者是方法则查找结束,最终会返回undefined
五.获取屏幕宽高
var screenWidth = document.body.clientWidth || document.documentElement.clientWidth;
var screenHeight = document.body.clientHeight || document.documentElement.clientHeight;
document.body.clientWidth/clientHeight || document.documentElement.clientWidth/clientHight;
六.获取元素自身长宽及据顶部左侧距离
xxx.offsetWidth/xxx.offsetHigth/xxx.offsetTop/xxx.offsetLeft
七.防抖与节流
1.防抖
定义:当事件触发后,等待一段时间在执行回调函数,如果在这段时间内,再次触发事件,则重新计时
即触发事件在n秒内只执行最后一次触发的函数(无论点击多少次都从最后一次开始计时,因为之前点击触发的定时器会被下次覆盖)
参数: 执行回调函数 / 延迟时间
debounce(执行回调函数), 延迟时间)
注意:定义防抖函数时 一定要把定时器放在return的函数中
用途: 输入框输入内容 滚动事件 按钮点击:防止用户多次快速点击
<script>
var box = document.getElementById("box");
let i = 1
function Count() {
box.innerText = i++;
}
function debounce(fn, delay) {
var timer = null;
return function () {
// 如果timer存在则清除定时器 否则进入计时器执行 此时再次点击又清除计时器 直到点击完成
if (timer) clearTimeout(timer);
timer = setTimeout(function () {
fn()
}, delay)
}
}
box.addEventListener('click', debounce(Count, 1000))
</script>
2.节流
定义: 限制函数在一定时间内的执行次数, 规定n秒内连续点击事件但只执行一次
在固定时间间隔内,函数最多只执行一次。无论事件触发多少次,都保证在指定时间内只执行一次。
即当在规定时间内频繁点击触发事件时 只执行第一次
参数: 执行回调函数 / 延迟时间
throttle(执行回调函数), 延迟时间)
用途:鼠标移动 鼠标跟踪 窗口大小 频繁点击按钮
<script>
var box = document.getElementById("box");
let i = 1
function Count() {
box.innerText = i++;
}
function throttle(fn, delay) {
var timer = null;
return function () {
// 触发事件时timer有值进入循环 此时再点击几次都不进循环 直到循环完成 timer被清空
if (!timer)
timer = setTimeout(function () {
fn()
timer = null
}, delay)
}
}
box.addEventListener('click', throttle(Count, 1000))
</script>
3.防抖与节流的区别
* 节流 保证函数在固定时间间隔内至少执行一次
* 防抖 在事件停止触发一段时间后才执行