###函数防抖与节流
前言:下列场景往往由于事件频繁被触发,因而频繁执行DOM操作、资源加载等重行为,导致UI停顿甚至浏览器崩溃:
- window对象的resize、scroll事件
- 拖拽时的mousemove事件
- 射击游戏中的mousedown、keydown事件
- 文字输入、自动完成的keyup事件
- 节流throttle。如果是第一次调用该函数,那么会马上调用func,否则就会记录当前时刻,当第二次调用的时间间隔超过wait时,才调用func。
- 防抖debounce。当调用动作n毫秒后才会执行该动作,如果在这n毫秒内又调用此动作则将重新计算执行时间。
事件循环机制
js是一个单线程的非阻塞脚本语言。单线程:js代码在执行的任何时候,都只有一个主线程来处理所有任务;非阻塞:当代码需要进行一项异步任务时,主线程会挂起pending这个任务,然后在异步任务返回结果时再根据一定规则去执行相应的回调。
同步代码:当一些列方法被依次调用的时候,因为Js是单线程的,同一时间只能执行一个方法,于是这些方法被排队在一个单独的地方,这个地方叫执行栈。 当一个脚本第一次执行的时候,js引擎会解析这段代码,并将其中的同步代码按照执行顺序加入执行栈中,然后从头开始执行。如果当前执行的是一个方法,那么js会向执行栈中添加这个方法的执行环境,然后进入这个执行环境继续执行其中的代码。当这个执行环境中的代码 执行完毕并返回结果后,js会退出这个执行环境并把这个执行环境销毁,回到上一个方法的执行环境。。这个过程反复进行,直到执行栈中的代码全部执行完毕。
执行栈是同步代码执行时执行上下文存在的空间。事件队列是异步事件返回结果时按照先后顺序排列所形成的。
异步代码:当js遇到一个异步代码时,首先会将其挂起,执行执行栈的其他任务,当异步代码返回结果后,js会将这个事件加入事件队列。被放入事件队列后不会立刻执行其回调,而是等待当前执行栈所有的任务都执行完毕,主线程处于闲置状态后,主线程会去查找事件队列是否有任务,如果有,那么从第一位的事件开始,将这个事件的回调放入执行站后,然后执行其中的同步代码。
但需要注意的是,异步任务之间也并不相同,因为他们的执行优先级有区别:
宏任务:setInterval,setTimeout
微任务:new Promise(), new MutainonObserver()
前面我们介绍过,在一个事件循环中,异步事件返回结果后会被放到一个任务队列中。然而,根据这个异步事件的类型,这个事件实际上会被对应的宏任务队列或者微任务队列中去。并且在当前执行栈为空的时候,主线程会 查看微任务队列是否有事件存在。如果不存在,那么再去宏任务队列中取出一个事件并把对应的回到加入当前执行栈;如果存在,则会依次执行队列中事件对应的回调,直到微任务队列为空,然后去宏任务队列中取出最前面的一个事件,把对应的回调加入当前执行栈…如此反复,进入循环。
当前执行栈执行完毕后,会优先处理所有微任务队列中的事件,然后再去宏任务队列中取出一个事件。同一次事件循环中,微任务永远在宏任务之前执行
new的模拟实现
构造函数如果返回一个对象,那么就返回这个对象,在返回之外定义的属性访问不到;如果构造函数返回的是一个返回值,那么只能访问到返回之外定义的属性。
function objectFactory(){
var obj = new Object();
Constructor = [].shift().call(arguments)//构造函数是传进去的数组中第一项
obj._proto_ = Constructor.prototype//可以访问到构造函数原型中的属性
Constructor.apply(obj,arguments);//可以访问到构造函数中的属性
return obj
}
arguments是个类似数组但不是数组的对象,存储的是实际传递给函数的参数。
本文探讨JavaScript中的函数防抖(debounce)与节流(throttle)技术,常用于优化频繁触发的事件处理,如window.resize、mousemove等。防抖确保在最后一次操作后执行,节流则按固定频率执行。同时,文章介绍了JavaScript的单线程、非阻塞特性和事件循环机制,包括执行栈、事件队列、宏任务和微任务的区别及其执行顺序。
4887

被折叠的 条评论
为什么被折叠?



