前端常见手撕

//数组扁平-------------------------------------------------------------------------------------------------------------------------------
const flat = (arr, depth = Infinity) => arr.reduce((total, cur) => {
    if(depth > 0 && Array.isArray(cur)){
        let flattened = flat(cur, depth - 1)
        return [...total, ...flattened]
    }
    else return [...total, cur]
}, [])
console.log(flat([1,[2,[3,4,[6]]],7,[8,[10]]], 1))

new URL
// url字符串解析-----------------------------------------------------------------------------------------------------------
const urlString = "https://www.example.com:8080/search?query=JavaScript&page=1#results";
const regex = /^(\w+):\/\/([^/:]+)(?::(\d+))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?$/;
const reg = /([a-z]+):\/\/([a-zA-Z0-9\.]+):?(\d+)?(.+(?=\?))\?([^#]*)#?(.*)/;

// 使用正则表达式匹配 URL 字符串,并提取各个部分
const matches = urlString.match(reg);
console.log(matches)
const [, protocol, hostname, port, pathname, search, hash] = matches;

// 获取查询参数
const queryParams = {};
search.replace(/([^=&]+)=([^&]*)/g, (match, key, value) => {
    queryParams[key] = decodeURIComponent(value);
});

console.log(protocol); // 输出:https
console.log(hostname); // 输出:www.example.com
console.log(port); // 输出:8080
console.log(pathname); // 输出:/search
console.log(search); // 输出:?query=JavaScript&page=1
console.log(hash); // 输出:#results
console.log(queryParams); // 输出:{query: "JavaScript", page: "1"}

//简单实现一个事件订阅机制,具有监听on和触发emit以及取消监听off方法------------------------------------------------------------------
class EventListen{
    constructor() {
        this.deps = {}
    }
    on(callback, eventName){
        if(!this.deps[eventName]){
            this.deps[eventName] = []
        }
        this.deps[eventName].push(callback)
    }
    emit(eventName, ...args){
        const callbacks = this.deps[eventName]
        if(callbacks){
            callbacks.forEach((callback) => {
                callback.apply(this, args)
            })
        }
    }
    //只订阅一次
    once(callback, eventName) {
        const onceCb = (...args) => {
            callback(...args);
            this.off(eventName, onceCb)
        }
        this.on(callback, onceCb)
    }
    off(eventName, callback){
        const callbacks = this.deps[eventName]
        if(callbacks){
            const index = callbacks.indexOf(callback)
            if(index >= 0){
                callbacks.splice(index,1)
            }
        }
    }
}
//简单实现一个promise.all---------------------------------------------------------------------------
function myAll(promiseList) {
    return new Promise((resolve, reject) => {
        let res = []
        promiseList.forEach((promise, index) => {
            Promise.resolve(promise).then(o => {
                res.push(o)
                if(index === promiseList.length - 1) resolve(res)
            }).catch(e => {
                reject(e)
            })
        })
    })
}
//简单实现一个深拷贝---------------------------------------------------------------------------
const deepClone = (obj)=> {
    const set = new WeakSet()
    set.add(obj)
    const copy = (obj) => {
        if(!obj || typeof obj !== 'object') return obj //基本数据类型
        const newObj = Array.isArray(obj) ? [] : {}
        for(let key in obj){
            let val = obj[key]
            if(typeof val != 'object'){
                newObj[key] = val
            }else{
                if(set.has(val)){
                    newObj[key] = null
                }else {
                    set.add(val)
                    newObj[key] = copy(val)
                }
            }
        }
        return newObj
    }
    return copy(obj)
}
const seven = {
    name: 'seven'
}
const juejin = {
    name: 'juejin',
    relative: seven
}
seven.relative = juejin
const newObj = deepClone(seven)
console.log(newObj)


//时间戳格式化---------------------------------------------------------------------------
function format(formatStr, timeStamp){
    timeStamp = new Date(timeStamp)
    const objs = {
        'Y+': timeStamp.getFullYear(),
        'M+': timeStamp.getMonth()+1,
        'd+': timeStamp.getDate(),
        'h+': timeStamp.getHours(),
        'm+': timeStamp.getMinutes(),
        's+': timeStamp.getSeconds()
    }
    for(let obj in objs){
        const reg = new RegExp(obj)
        if(reg.test(formatStr)){
            const value = objs[obj] + ''
            formatStr = formatStr.replace(reg, value)
        }
    }
    return formatStr
}

console.log(format('YY/MM/dd/hh:mm:ss',1659252290626))
//手写instanceof---------------------------------------------------------------------------
function myInstanceOf(instance, parent){
    if(!instance?._proto_ || ! parent.prototype) return false
    if(instance._proto_ === parent.prototype) return true
    return myInstanceOf(instance, parent.prototype)
}
//实现一个compose---------------------------------------------------------------------------
const compose = (...fns) =>
    // 注意 f、g 的位置,如果实现从左到右计算,则置换顺序
    fns.reduce((f, g) => (...args) => f(g(...args)))
//实现一个curry---------------------------------------------------------------------------
const curry = (fn, ...args1) => {
    let _length = fn.length
    return (...args2)=> {   //继续接收剩余参数
        let newArgs = [...args1, ...args2]
        if(newArgs.length >= _length) return fn(...newArgs)
        else return curry(fn, ...newArgs)
    }
}
const add = (x, y, z ,m) => x+y+z+m
let _add = curry(add,3)
console.log(_add(1,2)(4))
//数组转树---------------------------------------------------------------------------------------------------

let input = [
    { pid: 0, id: 1, name: "中国" },
    { pid: 1, id: 2, name: "广东" },
    { pid: 2, id: 3, name: "深圳" },
    { pid: 3, id: 6, name: "福田" },
    { pid: 1, id: 4, name: "香港" },
    { pid: 4, id: 5, name: "九龙" },
];
const arrayToTree = (arr) => {
    let map = {}
    for(let key of arr){
        map[key.id] = key
    }
    let res = []
    for(let key in arr){
        const node = arr[key]
        if(map[node.pid]){
            map[node.pid].children ? map[node.pid].children.push(node) : map[node.pid].children = [node]
        }else{
            res.push(node)
        }
        Reflect.deleteProperty(node, 'pid')
    }
    return res
}
const tree = arrayToTree(input)
console.log(tree)
//lodash.get---------------------------------------------------------------------------------------------------
function get (source, path, defaultValue = undefined) {
    // a[3].b -> a.3.b
    const paths = path.replace(/\[(\d+)\]/g, '.$1').split('.')
    let result = source
    for (const p of paths) {
        result = Object(result)[p]
        if (result === undefined) {
            return defaultValue
        }
    }
    return result
}

console.log(get( { a: [{ b: 1 }]}, 'a[0].b'))
//promise重试---------------------------------------------------------------------------

function retry(getData, times, delay) {
    return new Promise((resolve, reject) => {
        function attempt() {
            getData.then(resolve).catch((err) => {
                console.log(`还有${times}次机会`)
                if(times == 0) {
                    reject(err)
                } else {
                    times--
                    setTimeout(attempt(), delay)
                }
            })
        }
        attempt()
    })
}
//new----------------------------------------------------------------------------------------------------------------------------------
function _new(obj, ...rest){
    // 基于obj的原型创建一个新的对象
    const newObj = Object.create(obj.prototype);

    // 添加属性到新创建的newObj上, 并获取obj函数执行的结果.
    const result = obj.apply(newObj, rest);

    // 如果执行结果有返回值并且是一个对象, 返回执行的结果, 否则, 返回新创建的对象
    return typeof result === 'object' ? result : newObj;
}
class Scheduler {
    constructor() {
        this.tasks = [], // 待运行的任务
            this.usingTask = [] // 正在运行的任务
    }
    // promiseCreator 是一个异步函数,return Promise
    add(promiseCreator) {
        return new Promise((resolve, reject) => {
            promiseCreator.resolve = resolve
            if (this.usingTask.length < 2) {
                this.usingRun(promiseCreator)
            } else {
                this.tasks.push(promiseCreator)
            }
        })
    }
    usingRun(promiseCreator) {
        this.usingTask.push(promiseCreator)
        promiseCreator().then(() => {
            promiseCreator.resolve()
            let index = this.usingTask.findIndex(promiseCreator)
            this.usingTask.splice(index, 1)
            if (this.tasks.length > 0) {
                this.usingRun(this.tasks.shift())
            }
        })
    }
}
const timeout = (time) => new Promise(resolve => {
    setTimeout(resolve, time)
})
const scheduler = new Scheduler()
const addTask = (time, order) => {
    scheduler.add(() => timeout(time)).then(() => console.log(order))
}
addTask(400, 4)
addTask(200, 2)
addTask(300, 3)
addTask(100, 1)

//vue倒计时---------------------------------------------------------------------------https://juejin.cn/post/6882650885399248904#heading-0

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值