在vue监听器章节用到一个js插件lodash的函数去抖(debounce)和节流(throttle)功能,之前大概知道是防止重复调用的方法。
问题:事件频繁被触发而导致重复调用事件处理程序。
去抖:触发某个事件规定n秒后执行事件处理程序,如果在这n秒内相同的事件被重复触发,则重新计算事件处理程序的执行时间点,即将多次触发合并为1次触发。debounce首次js实现:http://unscriptable.com/2009/03/20/debouncing-javascript-methods/.
节流:如果事件一直被触发,而我们实际上需要定时的执行事件处理程序,则去抖方式就不再合适,因为去抖只能保证执行连续触发事件的最后一次调用。节流即:保证事件处理程序在大于等于预定周期时必定被执行1次,即以固定周期执行函数,从而降低执行次数。
高级定时器
js是单线程,定时器执行时间不能保证。浏览器对某个时间点代码执行优先级进行排序。js除了主执行进程外,还有一个在进程空闲时执行的任务队列。在js中,没有代码是立即执行的,需要等到进程空闲时执行。
问题:为什么说js是单线程,而又有个任务队列的概念?
function debounce(fn, delay) {
var timer = null;
return function () {
var _this = this;
var _args = arguments;
// 清除上一个timer
clearTimeout(timer);
// 当最后回调时,经过delay毫秒后执行事件处理程序
timer = setTimeout(function() {
fn.apply(_this, _args);
}, delay);
}
}
function throttle(fn, delay) {
var last = 0;
return function() {
var cur = +new Date();
if (cur - last > delay) {
fn.apply();
last = cur;
}
}
}
高级定时器
js是单线程,定时器执行时间不能保证。浏览器对某个时间点代码执行优先级进行排序。js除了主执行进程外,还有一个需要在进程空闲时执行的任务队列。在js中,没有代码是立即执行的,需要等到进程空闲时执行。
问题:为什么说js是单线程,而又有个任务队列的概念?
浏览器多进程架构:chrome每个tab页单独起一个进程,防止1个tab网页崩溃影响其他被打开的网页应用。相对于线程,进程之间不共享资源和地址空间。
浏览器内核:也称渲染引擎,处理获取的内容、整理信息(css)、计算并组合输出可视化的图像结果。
浏览器内核多线程:
GUI渲染线程(与JS引擎线程互斥,防止同时操作DOM)
JS引擎线程(与GUI渲染线程互斥)
定时触发线程
事件触发线程
异步HTTP请求线程
定时器工作原理是在指定时间后将定时任务代码插入到任务队列中,注意该代码不会立即执行,除非当前队列没有其他任务。js执行过程中如果遇到定时器,会交给浏览器的其他模块处理计时(例如:webkit的webcore模块),当到达指定延时后,回调函数被放入任务队列。
js事件循环机制,js主线程(main thread)、调用栈(call stack)、任务队列(task queue):
micro-task: process.nextTick, Promise, Object.observe, MutationObserver
macro-task: script整体,setTimeout, setInterval, setImmediate, I/O, UI rendering
执行顺序:调用栈 > micro-task > macro-task
例子:
(function test() {
setTimeout(function() {console.log(4)}, 0);
new Promise(function executor(resolve) {
console.log(1);
for( var i=0 ; i<10000 ; i++ ) {
i == 9999 && resolve();
}
console.log(2);
}).then(function() {
console.log(5);
});
console.log(3);
})()
以上输出结果为:1 2 3 5 4
网友评论