注:本文内容源于 哔哩哔哩 up主: 说人话的前端
防抖和节流有什么区别?手写防抖与节流
防抖与节流的共同点、区别及应用场景
代码实现
<body>
<h3>防抖</h3>
<input type="text" />
</body>
<script>
const oInp = document.querySelector("input")
oInp.addEventListener("keyup", debounce(function () {
console.log(oInp.value + "发送请求")
}))
function debounce(fn) {
let timer = null
return function () {
if (timer) clearTimeout(timer)
timer = setTimeout(() => {
fn.apply(this, arguments)
timer = null
}, 1000)
}
}
</script>
<body>
<h3>节流</h3>
<div draggable="true"></div>
</body>
<script>
const oDiv = document.querySelector("div")
oDiv.addEventListener("drag", throttle(function (e) {
console.log(e.clientX)
}))
function throttle(fn) {
let timer = null
return function () {
if (timer) return
timer = setTimeout(() => {
fn.apply(this, arguments)
timer = null
}, 1000)
}
}
</script>
什么是宏任务?什么是微任务?二者有什么区别?
什么是微任务?什么是宏任务?
微任务:Promise、async await
宏任务:setTimeout、setInterval、Ajax、DOM事件
二者的区别
先执行微任务,后执行宏任务
宏任务、微任务、DOM渲染的关系
1.Call Stack清空,触发Event Loop
2.执行微任务
3.DOM渲染
4.执行宏任务
完整Event Loop过程
Promise代码题
知识点
- JS 执行顺序:自上而下、先同步再异步、先微任务后宏任务
- new Promise() → Promise.resolve()
- then 和 catch 内部没有 throw new Error 相当于 resolve
- async function 相当于返回 Promise.resolve()
- await 后面的代码都是异步的
for…in、for…of 有什么区别
是否可枚举:Object.getOwnPropertyDescriptors(obj) -> enumerable: true
是否可迭代:arr[Symbol.iterator] () -> next()
扩展问题
for await … of 有什么作用?
出题目的:考察对异步的掌握情况
for await … of 用于遍历一组Promise
知识点
for await … of 逐个返回结果
Promise.al 返回一组结果
var、let 和 const 有什么区别?
var、let 和 const 的区别
1.块级作用域
var 没有块级作用域,let 和 const 有块级作用域
2.变量提升
var 有变量提升,let 和 const 没有变量提升
暂时性死区报错:let/const 会先被创建出来,但还未绑定值,所以不能用
3.重名
var允许重名,let 和 const 不允许重名(同一个作用域下)
说说原型和原型链是怎么回事?
复习class基础语法
- class
- construct
- extends
- super
- in stanceof
什么是原型
实例的隐式原型 === 类的显式原型
什么是原型链
手写 instanceof
知识点
instanceof
- instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上
- 可以判断继承关系,只要是在同一条原型链上,就可以返回 true
代码实现
while (true) {
if (obj1Proto === null) {
return false
} else if (obj1Proto === obj2Proto.prototype) {
return true
}
obj1Proto = obj1Proto.__proto__
}
手写 bind
知识点
- Function.prototype.myBind 挂载到函数原型上 fn.myBind
- Array.prototype.slice.call() 转为数组
- arg.shift() 返回下标为0的元素
代码实现
Function.prototype.myBind = function () {
const fn = this
const arg = Array.prototype.slice.call(arguments)
const _this = arg.shift()
return function () {
return fn.apply(_this, arg)
}
}
this 不同场景如何取值?
普通函数中的 this
- 严格模式下 this是undefined
- 非严格模式 this是window
call apply bind 中的 this
情况1 this是window
以 call 为例,bind、apply同理
- a.call()
- a.call(undefined)
- a.call(null)
情况2 传什么 this就是什么 - a.apply(‘abc’)
- a.call(123)
- const fn = a.bind({x:101}) fn()
定时器中的 this
情况1 定时器 + function
this 是 window
情况2 定时器 + 箭头函数
this 是上层作用域的 this
箭头函数中的 this
- 有 function 作用域的,this 是上层作用域的 this
- 没有 function 作用域的,this 是 window
值类型与引用类型有什么区别
值类型
- String
- Number
- Boolean
- Symbol
引用类型
- Json
- Array
- null
手写深拷贝
JSON.parse(JSON.Stringfy(obj))
不能存放函数、时间对象、正则等
递归
没有考虑循环引用
function deepClone(obj) {
if (typeof (obj) !== "Object" || obj == null) {
return obj
}
let res = obj instanceof Array ? [] : {}
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
res[key] = deepClone(obj[key])
}
}
return res
}
lodash.cloneDeep
推荐使用 工作中没必要重复造轮子
何时使用 == ,何时使用 ===
== 会产生隐式类型转换
100 == '100'
0 == ''
0 == false
false == ''
null == undefined
只有obj == null 使用双等
相当于
if (obj === bull || obj === undefined) {
}
什么是truly变量?什么是falsely变量?
truly变量
!!val === true
falsely变量
!!val === false
除了以下五种falsely变量,都是truly变量
- 数字0
- NaN
- 空字符串
- null
- undefined
什么是闭包
概念
闭包是作用域的一种特殊应用
触发闭包的情况
1、函数当做返回值被返回
2、函数当做参数被传递
3、自执行匿名函数
闭包的应用
1、隐藏变量
2、解决 for i 的问题
作用域
全局作用域、局部作用域
自由变量
不在自己作用域里的变量,就是自由变量
自由变量的值:在函数定义的地方向上层作用域查找。与函数调用位置无关
手写 flat 方法拍平数组
知识点
Array.concat
- Array.concat(1,2,[3,4,5])
判断是不是数组
- xxx instanceof Array
function flat(arr) {
while (arr.some((item) => item instanceof Array)) {
arr = Array.prototype.concat.apply([], arr)
}
return arr
}
数组去重
set方法
function unique(arr) {
const set = new Set(arr)
return [...set]
}
forEach + indexOf
function uniq(arr) {
const res = []
arr.forEach(item => {
if (res.indexOf(item) === -1) {
res.push(item)
}
});
return res
}
求数组最大值
- Math.max
function getMax(arr) {
return Math.max(...arr)
return Math.max.apply(null, arr)
}
- Array.sort
function getMax(arr) {
arr.sort((n1, n2) => {
return n2 - n1
})
return arr[0]
}
- Array.reduce
function getMax(arr) {
arr.reduce((n1, n2) => {
return n1 > n2 ? n1 : n2
})
}