// 防抖
function debounce(fn, delay) {
let timer
return function(...args) {
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(() => {
fn.apply(this, args)
}, delay)
}
}
// 节流
function throttle(fn, delay) {
let last = 0
return function(...args) {
let now = Date.now()
if (now - last >= delay) {
fn.apply(this, args)
last = now
}
}
}
// 深拷贝
function deepClone(obj, cache = new WeakMap()) {
if (!obj || typeof obj !== 'object') return obj
if (cache.get(obj)) return cache.get(obj)
let cloneObj = Array.isArray(obj) ? [] : {}
cache.set(obj, cloneObj)
for(let key in obj) {
if (obj.hasOwnProperty(key)) {
const temp = obj[key]
cloneObj[key] = typeof temp === 'object' ? deepClone(temp, cache) : temp
}
}
return cloneObj
}
const obj = { name: 'Jack', address: { x: 100, y: 200 } }
obj.a = obj // 循环引用
const newObj = deepClone(obj)
// console.log(newObj.address === obj.address) // false
class MyPromise {
constructor(executor) {
this.status = 'pending'
this.value = null
this.errValue = null
this.fulfilledCallbacks = []
this.rejectedCallbacks = []
const that = this
function resolve(value) {
if (that.status === 'pending') {
that.status = 'resolved'
that.value = value
that.fulfilledCallbacks.forEach(fn => fn(that.value))
}
}
function reject(value) {
if (that.status === 'pending') {
that.status = 'rejected'
that.errValue = value
that.rejectedCallbacks.forEach(fn => fn(that.value))
}
}
try {
executor(resolve, reject)
} catch(err) {
reject(err)
}
}
then(onFulfilled, onRejected) {
if (this.status === 'pending') {
this.fulfilledCallbacks.push(() => {
onFulfilled(this.value)
})
this.rejectedCallbacks.push(() => {
onRejected(this.errValue)
})
}
if (this.status === 'resolved') {
onFulfilled(this.value)
}
if (this.status === 'rejected') {
onRejected(this.errValue)
}
}
// then实现链式调用
then1(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value
onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err }
let promise2 = new MyPromise((resolve, reject) => {
if (this.status === 'pending') {
this.fulfilledCallbacks.push(() => {
setTimeout(() => {
try{
const x = onFulfilled(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch(err) {
reject(err)
}
}, 0)
})
this.rejectedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onRejected(this.errValue)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
})
}
if (this.status === 'resolved') {
setTimeout(() => {
try {
const x = onFulfilled(this.value)
resolvePromise(promise2, x, resolve, reject)
}catch(e) {
reject(e)
}
},0 )
}
if (this.status === 'rejected') {
setTimeout(() => {
try {
let x = onRejected(this.errValue)
resolvePromise(promise2, x, resolve, reject)
} catch(e) {
reject(e)
}
}, 0)
}
})
return promise2
}
catch(fn) {
return this.then1(null, fn)
}
// finally(fn) {
// return this.then1(fn, fn)
// }
}
function resolvePromise(promise2, x, resolve, reject) {
if (x === promise2) {
return reject(new Error('循环引用'))
}
let flag = false
if(x && (typeof x === 'object' || typeof x === 'function')) {
try {
let then = x.then
if (typeof then === 'function') {
then.call(x, y=> {
if (flag) return
flag = true
resolvePromise(promise2, y, resolve, reject)
}, err => {
if (flag) return
flag = true
reject(err)
})
} else {
resolve(x)
}
} catch(err) {
if (flag) return
flag = true
reject(err)
}
} else {
resolve(x)
}
}
MyPromise.resolve = function(value) {
return new MyPromise((resolve, reject) => {
resolve(value)
})
}
MyPromise.reject = function(value) {
return new MyPromise((resolve, reject) => {
reject(value)
})
}
MyPromise.all = function(promises) {
return new MyPromise((resolve, reject) => {
let res = [], count = 0, len = promises.length
for (let i = 0; i < len; i++) {
promises[i].then(data => {
res[i] = data
count++
if (count === len) {
resolve(res)
}
}, (err) => {
reject(err)
})
}
})
}
MyPromise.race = function(promises) {
let len = promises.length
return new MyPromise((resolve, reject) => {
for (let i = 0; i < len; i++) {
promises[i].then(data => {
resolve(data)
}, (err) => {
reject(err)
})
}
})
}
MyPromise.any = function(promises) {
return new MyPromise((resolve, reject) => {
let index = 0, len = promises.length
for (let i = 0; i < len; i++) {
promises[i].then(data => {
resolve(data)
}, (err) => {
index++
if (index === len) {
reject(new Error('All promises rejected'))
}
})
}
})
}
MyPromise.allSettled = function(promises) {
if (promises.length === 0) return MyPromise.resolve([])
return new MyPromise((resolve, reject) => {
let res = [], count = 0, len = promises.length
for (let i = 0; i < len; i++) {
promises[i].then(value => {
res[i] = {
status: 'fulfilled',
value
}
count++
if (count === len) {
resolve(res)
}
}, reason => {
res[i] = {
status: 'rejected',
reason
}
count++
if (count === len) {
reject(res)
}
})
}
})
}
MyPromise.prototype.finally = function(fn) {
return this.then1((data) => {
return MyPromise.resolve(fn()).then(() => data)
}, err => {
return MyPromise.resolve(fn()).then(() => { throw err })
})
}
// 测试
const fn = new MyPromise((resolve, reject) => {
setTimeout(() => {
if(Math.random() > 0.6) {
resolve(1)
} else {
reject(2)
}
}, 1000)
})
// fn.then(
// res => {
// console.log('res', res) // res 1
// },
// err => {
// console.log('err', err) // err 2
// }
// )
// fn.then1(res => {
// console.log('res1111', res) // res 1
// }).then1(() => {
// console.log('aaa')
// })
// fn.then1(res => {
// console.log('res1111', res) // res 1
// }).catch((err) => {
// console.log(err)
// }).finally(() => {
// console.log('finally')
// })
function limitRequest(urls = [], limit = 5) {
return new Promise((resolve, reject) => {
const len = urls.length
let count = 0
const start = async () => {
const url = urls.shift()
if (url) {
try{
await axios.post(url)
if (count === len - 1) {
resolve()
} else {
count++
start()
}
} catch(err) {
count++
start()
}
}
}
while(limit > 0) {
start()
limit--
}
})
}
// ES5 寄生组合式继承
function Parent(name) {
this.name = name
}
Parent.prototype.sayName = function() {
console.log('My name is ' + this.name)
}
function Child(name, age) {
Parent.call(this, name)
this.age = age
}
Child.prototype = Object.create(Parent.prototype)
Child.prototype.constructor = Child
Child.prototype.eat = function() {
console.log(this.name + 'is eating')
}
// sort排序
var arr= [2, 3, 6, 8, 1, 5, 4, 9]
arr.sort((a, b) => a-b) // 升序
// console.log(arr)
arr.sort((a, b) => b-a) // 降序
// console.log(arr)
// 冒泡排序
function bubbleSort(arr) {
let len = arr.length
for (let i = 0; i < len; i++) {
for(let j = 0; j < len - i; j++) {
if (arr[j] > arr[j + 1]) {
let temp = arr[j]
arr[j] = arr[j + 1]
arr[j + 1] = temp
}
}
}
return arr
}
// console.log(bubbleSort([2, 3, 6, 8, 1, 5, 4, 9])) // [1, 2, 3, 4, 5]
// 数组去重
var arr = [1, 1, 2, 3, 3]
var newArr = [...new Set(arr)]
// console.log(newArr) // [1, 2, 3]
var newArr = Array.from(new Set(arr))
// console.log(newArr) // [1, 2, 3]
function unique(arr) {
let res = []
arr.forEach(item => {
if (res.indexOf(item) === -1) {
res.push(item)
}
})
return res
}
// console.log(unique(arr)) // [1, 2, 3]
function unique(arr) {
return arr.filter((item, index, arr) => {
return arr.indexOf(item) === index
})
}
// console.log(unique(arr)) // [1, 2, 3]
function unique(arr) {
return arr.reduce((acc, cur) => {
if (!acc.includes(cur)) {
acc.push(cur)
}
return acc
}, [])
}
// console.log(unique(arr)) // [1, 2, 3]
// 获取url上的参数
function getParams(url) {
const res = {}
let str = ''
if (url.includes('?')) {
str = url.split('?')[1]
}
if (url.includes('#')) {
str = str.split('#')[0]
}
const arr = str.split('&')
arr.forEach(item => {
const [key, val] = item.split('=')
// res[key] = val
res[key] = decodeURIComponent(val)
})
return res
}
var user = getParams('http://www.baidu.com?user=%E9%98%BF%E9%A3%9E&age=16')
// console.log(user) // { user: '阿飞', age: '16' }
var user = getParams('http://www.baidu.com?user=%E9%98%BF%E9%A3%9E&age=16#hasKey')
// console.log(user) // { user: '阿飞', age: '16' }
// 事件总线|发布订阅模式
class EventEmitter {
constructor() {
this.cache = {}
}
on(name, fn) {
if (this.cache[name]) {
this.cache[name].push(fn)
} else {
this.cache[name] = [fn]
}
}
off(name, fn) {
const tasks = this.cache[name]
if (tasks) {
const index = tasks.findIndex(f => f === fn || f.callback === fn)
if (index > -1) {
tasks.splice(index, 1)
}
}
}
emit(name, once=false) {
if (this.cache[name]) {
const tasks = this.cache[name].slice()
for(let fn of tasks) {
fn()
}
if (once) {
delete this.cache[name]
}
}
}
}
const eventBus = new EventEmitter()
const task1 = () => { console.log('task1'); }
const task2 = () => { console.log('task2'); }
eventBus.on('task', task1)
eventBus.on('task', task2)
eventBus.off('task', task1)
setTimeout(() => {
// eventBus.emit('task') // task2
}, 1000)
// 数组扁平化
function flatArr(arr, depth = 1) {
if (!Array.isArray(arr) || depth <= 0) return arr
let res = arr.reduce((prev, cur) => {
if (Array.isArray(cur)) {
return prev.concat(flatArr(cur, depth - 1))
} else {
return prev.concat(cur)
}
}, [])
return res
}
var arr = [1, 2, [3, 4], [5, [6, 7]]]
// console.log(flatArr(arr, 3))
Array.prototype.myForEach = function(fn) {
if (!this || !Array.isArray(this)) {
throw new Error('this must be an Array')
}
if (typeof fn !== 'function') {
throw new Error('fn must be a function')
}
const arr = this, thisArg = arguments[1] || window, len = this.length
for (let i = 0; i < len; i++) {
fn.call(thisArg, arr[i], i, arr)
}
}
Array.prototype.myReduce = function(fn) {
if (!this || !Array.isArray(this)) {
throw new Error('this must be an Array')
}
if (typeof fn !== 'function') {
throw new Error('fn must be a function')
}
const arr = this, len = this.length
let res = arguments[1], i = 0
if (res === undefined) {
if (len === 0) {
throw new Error('initVal and array.length need one')
}
res = arr[i]
i++;
}
for (;i < len; i++) {
res = fn(res, arr[i], i, arr)
}
return res
}
var arr = [1, 2, 3, 4]
var sum = arr.myReduce((prev, next) => {
return prev + next
}, 0)
// console.log(sum) // -> 10
function createObj(fn) {
const obj = Object.create(null)
// obj.__proto__ = fn.prototype
Object.setPrototypeOf(obj, fn.prototype)
let res = fn.apply(obj, [].slice.call(arguments, 1))
return res && (typeof res === 'object' || typeof res === 'function') ? res : obj
}
var arr = [1, 1, 2, 3, 3, 4, 4, 3, 5]
function dd(arr) {
let res = []
let temp = []
arr.forEach((item, index) => {
if (!temp.includes(item)) {
temp[index] = item
}
if (!temp[index] && !res.includes(item)) {
res.push(item)
}
})
return res
}
// console.log(dd(arr))
var str = "100000000",
reg = /(?=(\B\d{3})+$)/g;
str = str.replace(reg, ",")
// console.log(str)
// 将数字每千分位用逗号隔开
function formatNum(num) {
let numStr= num.toString(),
intNum = numStr,
xiaoshu = ''
if (numStr.indexOf('.') > -1) {
[intNum, xiaoshu] = numStr.split('.')
}
let res = []
intNum.split('').reverse().forEach((item, index, arr) => {
res.push(item)
if (index > 0 && index % 3 === 2 && index < arr.length - 1) {
res.push(',')
}
})
intNum = res.reverse().join('')
return xiaoshu ? intNum + '.' + xiaoshu : intNum
}
// console.log(formatNum(str))
// console.log(formatNum(100343333.55))
function lengthOfLongestSubstring(s) {
let map = new Map(),
res = 0,
i = -1,
len = s.length
for(let j = 0; j < len; j++) {
if (map.has(s[j])) {
i = Math.max(i, map.get(s[j]))
}
res = Math.max(res, j - i)
map.set(s[j], j)
}
return res
}
console.log(lengthOfLongestSubstring('adrrefsfds'))
console