共计 3182 个字符,预计需要花费 8 分钟才能阅读完成。
1. 扁平化嵌套数组 /flat 实现
描述:将嵌套多层的数组展开平铺成只有一层的数组。
let array = [1, [1, 2, 3], [1, [2, {}]] ]
handle(array) // [1, 1, 2, 3, 1, 2, {}]
方法一:
const handle = array => JSON.parse(`[${JSON.stringify(arr).replace(/\[|]/g,”)}]`)
handle(array) // [1, 1, 2, 3, 1, 2, {} ]
知识点:JSON.parse()/JSON.stringify()、String.prototype.replace()
方法二:
const handle = array => array.reduce((accumulator, currentValue) => accumulator.concat(Array.isArray(currentValue) ? hanlde(currentValue), currentValue), [])
handle(array) // [1, 1, 2, 3, 1, 2, {} ]
知识点:Array.prototype.reduce()、Array.prototype.concat()
方法三:
const handle = array => {
while(array.some(item => Array.isArray(item))) {
array = [].concat(…array)
}
return array
}
handle(array) // [1, 1, 2, 3, 1, 2, {} ]
知识点:while、Array.prototype.some()、展开语法 (Spread syntax)
其它方法:……
2. 数组去重
描述:将数组中重复的元素过滤掉。
let array = [1, 2, 1, ‘3’, ‘3’, 0 , 1]
handle(array) // [1, 2, ‘3’, 0]
方法一:
const handle = array => […new Set(array)]
handle(array) // [1, 2, ‘3’, 0]
知识点:Set
方法二:
const handle = array => array.reduce((accumulator, currentValue) => {
!accumulator.includes(currentValue) && accumulator.push(currentValue)
return accumulator
}, [])
handle(array) // [1, 2, ‘3’, 0]
知识点:Array.prototype.includes()
方法三:
const handle = array => {
let map = new Map()
return array.filter(item => map.has(item) ? false : map.set(item))
}
handle(array) // [1, 2, ‘3’, 0]
知识点:Map、Array.prototype.filter()
其它方法:……
3. 模拟 bind 实现
Function.prototype.bind = function () {
let self = this, args = Array.from(arguments), context = args.shift();
return function () {
return self.apply(context, args.concat(…arguments))
};
};
知识点:apply、call、bind
4. 模拟 New 实现
const handle = function() {
let fn = Array.prototype.shift.call(arguments)
let obj = Object.create(fn.prototype)
let o = fn.apply(obj, arguments)
return typeof o === ‘object’ ? o : obj;
}
知识点:Object.create()
5. 格式化数字
const num = 123456789;
const handle = num => String(num).replace(/\B(?=(\d{3})+(?!\d))/g, ‘,’)
handle(num) // 123,456,789
知识点:正则表达式、String.prototype.replace()
6. 回文判断
const num = 123456654321;
const str = ‘abababababab’;
const handle = params => {
let str_1 = String(params).replace(/[^0-9A-Za-z]/g, ”).toLowerCase();
let str_2 = str_1.split(”).reverse().join();
return str_1 === str_2 ? true : false
}
handle(num) // true
handle(str) // false
知识点:String.prototype.split()、Array.prototype.join()
7. 函数节流
定时器
const handle = (fn, interval) => {
let timeId = null;
return function() {
if (!timeId) {
timeId = setTimeout(() => {
fn.apply(this, arguments)
timeId = null
}, interval)
}
}
}
知识点:window.setTimeout
时间戳
const handle = (fn, interval) => {
let lastTime = 0
return function () {
let now = Date.now();
if (now – lastTime > interval) {
fn.apply(this, arguments)
lastTime = now
}
}
}
8. 函数防抖
const handle = (fn, delay) => {
let timeId;
return function() {
if (timeId) clearTimeout(timeId)
timeId = setTimeout(() => {
fn.apply(this, arguments)
}, delay)
}
}
函数节流、函数防抖区别:函数节流和函数防抖较容易混淆,可以这么比喻,对于函数节流,门外有人频繁敲门,但是门卫按固定时间来决定是否开门。对于函数防抖,门外有人频繁敲门,门卫按最后一次敲门来决定是否开门。
知识点:window.clearTimeout
9. 发布订阅模式
class Pubsub {
constructor() {
this.handles = {}
}
subscribe(type, handle) {
if (!this.handles[type]) {
this.handles[type] = []
}
this.handles[type].push(handle)
}
unsubscribe(type, handle) {
let pos = this.handles[type].indexOf(handle)
if (!handle) {
this.handles.length = 0
} else {
~pos && this.handles[type].splice(pos, 1)
}
}
publish() {
let type = Array.prototype.shift.call(arguments)
this.handles[type].forEach(handle => {
handle.apply(this, arguments)
})
}
}
const pub = new Pubsub()
pub.subscribe(‘a’, function() {console.log(‘a’, …arguments)})
pub.publish(‘a’, 1, 2, 3)
// a 1 2 3