防抖(debounce)
不断地执行一个函数时,如果函数在某个时间段再次被执行,则会重新计算时间而不执行函数
在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。
对于一些处理时间比较久的函数,使用防抖会减低性能的消耗,对比 throttle,触发的次数会少
对于连续执行函数时,防抖只会执行一次
节流(throttle)
不断地执行一个函数时,过了某个时间还在执行的时候,就会再次被执行
在连续触发函数时,每隔 n 秒会触发一次函数
在 github
看到一位朋友 bodyno
说的一句解释:
一个是多久触发一次
一个是延迟多久触发
获取 url 的 query 参数
javascript
function getQuery(str) {
const arr = str.split('?')
if (!arr[1]) return {}
return arr[1].split('&').reduce((acc, cur) => {
const val = cur.split('=')
return {
...acc,
[decodeURIComponent(val[0])]: decodeURIComponent(val[1])
}
}, {})
}
判断数据类型方法
javascript
function checkType(val) {
return Object.prototype.toString.call(val).replace(/(\[object)|\]/g, '').toLowerCase()
}
加密字符串方法
javascript
// 凯撒密码
const encodeCaesar = ({str = "", padding = 3}) =>
!str
? str
: str
.split("")
.map((s) => String.fromCharCode(s.charCodeAt() + padding))
.join("");
const decodeCaesar = ({str = "", padding = 3}) =>
!str
? str
: str
.split("")
.map((s) => String.fromCharCode(s.charCodeAt() - padding))
.join("");
console.log(encodeCaesar({str: "hello world"}));
console.log(decodeCaesar({str: "khoor#zruog"}));
apply, call 实现
apply 和 call 类似,改变方法的上下文去执行;区别在传参,call 是一个个的传入,apply 是传入一个数组
javascript
Function.prototype.mockApply = function(context, args) {
// 缓存上下文
context._fn = this
// 执行方法
const result = context._fn(...args)
delete context._fn
return result
}
Function.prototype.mockCall = function(context, ...args) {
// 缓存上下文
context._fn = this
// 执行方法
const result = context._fn(...args)
delete context._fn
return result
}
const obj1 = {
a: 'obj1'
}
const obj2 = {
a: 'obj2',
fn: function(b, c) {
return this.a + (b || '') + (c || '')
}
}
console.log(obj2.fn())
console.log(obj2.fn.mockApply(obj1, ['b']))
console.log(obj2.fn.mockCall(obj1, 'b', 'c'))
bind 实现
bind 就是柯里化函数,执行了会改变方法的上下文,并返回一个函数
javascript
Function.prototype.mockBind = function(context, ...args) {
let _this = this
return function(...args2) {
return _this.apply(context, [...args, ...args2])
}
}
function bind(fn, context) {
return function() {
return fn.apply(context, arguments)
}
}
const obj1 = {
a: 'a1',
fn: function(b, c) {
return this.a + b + c
}
}
const obj2 = {
a: 'a2'
}
console.log(obj1.fn('b', 'c'))
console.log(obj1.fn.bind(obj2, 'b')('c'))
curry
javascript
function curry(...args) {
if (args.length > 1) return args2.reduce((acc, cur) => acc + cur, 0)
let val = 0
function add(...args2) {
val = args2.reduce((acc, cur) => acc + cur, val)
return add
}
add.toString = function() { return val }
val = args[0]
return add
}
// curry(1,6)(2,5)(3,4)(7,8,9) -> 45
// curry(1) -> 1
这是个加法的 curry 函数
利用 .toString
方法和闭包特性,实现切割参数执行的功能
curry 函数的主要实现,是将被返回函数的参数进行排序
flattenDeep
javascript
function flattenDeep(arr) {
return arr.reduce((acc, cur) => {
const _val = Array.isArray(cur) ? flattenDeep(cur) : [cur]
return [...acc, ..._val]
}, [])
}
console.log(flattenDeep(
[
1, 2, 3, [4, 5, [6, 7, [8, 9]]]
]
))
深克隆
javascript
function deepClone(val) {
function getType(_val) {
return Object.prototype.toString.call(_val).replace(/[\[\s\]]|(object)/g, '')
}
const valType = getType(val);
if (valType !== 'Object' && valType !== 'Array') return val
let output = {}
if (valType === 'Array') {
output = []
val.forEach(v => {
const curValType = getType(v)
if (curValType === 'Array' || curValType === 'Object') {
output.push(deepClone(v))
} else {
output.push(v)
}
})
} else if (valType === 'Object') {
Object.keys(val).forEach(v => {
const curValType = getType(v)
if (curValType === 'Array' || curValType === 'Object') {
output[v]= (deepClone(val[v]))
} else {
output[v]= (val[v])
}
})
}
return output
}
const obj = {
a: 1,
b: [
{
b1: 'b1',
b2: {
b2_1: 'b2_1'
}
}
]
}
const clone = deepClone(obj)
obj.b = { b: 'b' }
console.log(clone)
console.log(obj)
实现并集
javascript
function union(a, b) {
return a.reduce((acc, cur) => {
if (b.includes(cur)) acc.push(cur)
return acc
}, [])
}
const a = [1,2,3,4,5]
const b = [2,3,6,7,8,3,2,3,4]
// 期待输出:[2,3,4]
console.log(union(a, b))
一维数组转树
javascript
function listToTree(data) {
let arr = JSON.parse(JSON.stringify(data))
const listChildren = (obj, filter) => {
[arr, obj.children] = arr.reduce((res, val) => {
if (filter(val))
res[1].push(val)
else
res[0].push(val)
return res
}, [[],[]])
obj.children.forEach(val => {
if (arr.length)
listChildren(val, obj => obj.parentId === val.id)
})
}
const tree = {}
listChildren(tree, val => arr.findIndex(i => i.id === val.parentId) === -1)
return tree.children
}