介绍防抖节流原理、区别以及应用,并用Javascript进行实现
防抖
- 原理:在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。
使用场景:
* 提交按钮场景: 防止多次提交按钮,只执行最后提交的一次 * 搜索框联想场景:防止联想发送请求,只发送最后一次输入
简易版本实现
function debounce(fn, delay) { let timer = null return (...args) => { clearTimeout(timer) timer = setTimeout(() => { fn.apply(this, args) }) } }
立即执行版
* 立即执行函数,然后等到停止触发n秒后,才可以重新触发执行。
function debounce(fn, delay, immediate) { let timer; return (...args) => { if (timer) clearTimeout(timer) if (immediate) { const callNow = !timer timer = setTimeout(() => { timer = null }, delay) if (callNow) fn.apply(this, args) } else { timer = setTimeout(() => { fn.apply(this, args) }, delay) } } }
节流
- 原理:规定一个单位时间内,只能触发一次函数。如果这个单位时间内多次触发函数,只有一次生效。
使用场景
* 拖拽场景:固定时间内只执行一次,防止超高频次触发位置变动 * 缩放场景:监控浏览器resize
使用定时器实现
function throttle(fn, delay) { let timer return (...args) => { if (!timer) { timer = setTimeout(() => { timer = null fn.apply(this, args) }, delay) } } }
闭包
什么是必闭包
可在内部函数访问外部函数的作用域。在javascript中,每当创建一个函数,闭包就会在函数创建的同时创建出来。
优点
* 可从内部函数访问外部函数作用域中的变量,且访问到的变量长期驻扎在内存中,可供之后使用 * 避免变量污染全局 * 把变量存到独立作用域,作为私有成员存在
缺点
* 对内存消耗有负面影响。因内存函数保存对外层函数引用,导致无法垃圾回收,增大内存使用量
应用场景
循环中创建闭包,防止取到意外值
for(var i = 0; i < 3; i ++) { document.getElementById('id'+i).onfocus = function() { alert(i) } } //使用闭包解决 function makeCallBack(num) { return function() { alert(num) } } for(var i = 0; i < 3; i ++) { document.getElementById('id'+i).onfocus = makeCallBack(i) }
模块封装
var A = (function(){ var foo = 0; //声明为模块私有变量,外界无法访问 function A() {} A.prototype.bar = function B() { return foo } return A }())
事件循环机制(node、浏览器)
为什么会有Event Loop
Javascript任务分两种`同步`和`异步`,`同步任务`是直接放在主线程上排队一次执行,`异步任务`会放在任务队列中,若有多个异步任务,则需要在任务队列中排队等待,任务队列类似缓冲区,任务下一步会被移动到`调用栈`然后主线程执行调用栈 Javascript是`单线程`的
Promise的特性、优缺点,内部是如何实现的,动手实现Promise
promise
基本特性- 三种状态:
pending
、fulfilled
、rejected
- 接受一个回调函数作为参数,该回调函数接受两个参数,分别为
resolve
和reject
;另外resolve
的值除了正常值以外,还可能是一个Promise
对象的实例;reject
通常是error
对象实例 then
方法返回一个新的Promise
实例,并接收两个参数onResolved
(fufilled状态回调);onRejected
(reject状态回调,改参数可选)- catch方法返回一个新的
Promise
实例 - finally方法不管
Promise
状态如何都会执行,该方法回调函数不需要接受任何参数
- 三种状态:
简单版本
class Promise { constrcutor (executor) { ths.state = 'pending' this.value = undefined this.reason = undefined let resolve = value => { if (this.state === 'pending') { this.state = 'fulfilled' this.value = value } }; let reject = value => { if (this.state === 'pending') { this.state = 'rejected' this.reason = reason } }; try { executor(resolve, reject) } catch (err) { reject(err) } } then (onFulfilled, onRejected) { if (this.state == 'fulfilled') { let x = onFulfilled(this.value) } if (this.state === 'rejected') { let x = onRejected(this.reason) } } }
面试够用版
function myPromise(constructor) { let self = this; self.state = 'pending'; //定义状态改变前初始状态 self.value = unbdefined; //定义状态为resolved的时候的状态 self.reason = undefined; //定义状态为rejected的时候的状态 function resovle (value) { //两个==='pending' 保证了状态的改变是不可逆转的 if (self.state === 'pending') { self.value = value self.status = 'resolved' } } function reject(reason) { if (self.state === 'pending') { self.reason = reason; self.status = 'rejected' } } // 捕获构造函数异常 try { constructor(resolve, reject) } catch (err) { reject(err) } } myPromise.prototype.then = function(onFulfilled, onRejected) { let self = this; switch (self.status) { case 'resolved': onFulFilled(self.value); break; case 'rejected': onRejected(self.reason); break; default: } }
//测试
var p = new myPromise((resolve, reject) => {resolve(1)})
p.then((x) => {console.log(x)}) //输出
```
- typeof返回一个表示类型的字符串
typeof的结果列表
类型 | 结果 |
---|---|
Undefined | "undefined" |
Null | "object" |
Boolean | "boolean" |
Number | "number" |
String | "string" |
Symbol | "symbol" |
Function | "function" |
Object | "object" |
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。