前端手写函数汇总

一、js篇

1、防抖函数

防抖:指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间

function debounce(fn,t){
    let timer=0
    // 返回一个匿名函数,为了能够一直调用
    return function(){
        // 如果已经存在setTimeout定时器先删除,再添加新定时器
        if(timer) clearTimeout(timer)
        timer=setTimeout(function(){
            fn()
        },t)

    }

}

2、节流函数

节流:连续触发事件但是在 n 秒中只执行一次函数

function throttle(fn,t){
    let timer
    return function(){
        // 和防抖区别在于清空定时器放在setTimeout里面
        if(!timer){
        timer=setTimeout(function(){
            fn()
            // 不能用clearTimeout,因为在定时器运行中情况定时器是不合理的
            timer=null
        },t)
        }
    }
}

3、call函数

4、apply函数 

5、bind函数

 6、Promise

Promise的自定义封装和一些API的封装 

// 我自己的Promise构造函数
// 这里的executor是接住了一个匿名函数,所以可以加括号传参调用

function Promise(executor) {
    // 添加属性
    this.promiseState = 'pending'
    this.promiseResult = null
    // 声明属性
    this.callbacks = []
    // 保存实例对象this的值,因为resolve调用是直接 resolve('OK')这样调用,所以他的this是指向window的
    const self = this
    // resolve函数
    function resolve(data) {
        // 判断状态,保证状态只被修改一次
        if (self.promiseState !== 'pending') return
        // 1、改变状态(promiseState)
        self.promiseState = 'fulfilled'//resolved
        // 2、设置对象结果值(promiseResult)
        self.promiseResult = data
        // 调用成功的回调函数
        // 当我的函数是异步时,也就是executor中有个定时器,就会在定时器结束后才会改变状态
        // 就会导致不会触发then,因为then中是有状态===fulfilled或rejected才会调用我传入的匿名函数
        // 所以加上pending状态的判断,当我状态没改变就运行到then时(有个定时器),
        // 用一个对象保存下两个匿名函数,当定时器时间结束,执行executor时
        // 就会调用对应的resolve或reject,就会调用到这里
        // 从而去调用then中的匿名函数,实现状态改变之后再回调
        setTimeout(() => {
            self.callbacks.forEach(item => {
                item.onResolved(data)
            })
        })

    }
    // reject函数
    function reject(data) {
        // 判断状态,保证状态只被修改一次
        if (self.promiseState !== 'pending') return
        // 1、改变状态(promiseState)
        self.promiseState = 'rejected'
        // 2、设置对象结果值(promiseResult)
        self.promiseResult = data
        // 调用失败的回调函数
        setTimeout(() => {
            self.callbacks.forEach(item => {
                item.onRejected(data)
            })
        })

    }
    try {
        // 同步调用executor函数
        executor(resolve, reject)
    } catch (error) {
        // 修改promise对象状态为失败
        reject(error);
    }


}

// 原型中定义then
// 这里的onResolved和onRejected是接住了一个匿名函数,所以可以加括号传参调用
Promise.prototype.then = function (onResolved, onRejected) {
    const self = this// 这个self是p

    // 这里是实现catch的异常穿透
    // 因为原版的promise在使用异常穿透的时候,允许用户在then只传入一个参数
    // 也就是成功时候的回调函数,失败的回调函数统一到catch中处理
    // 判断回调函数参数,也就是我没传入onRejected参数
    // 没传onRejected参数时,为防止报undifild错误,直接默认指定一个
    if (typeof onRejected != 'function') {
        onRejected = reason => {
            throw reason
        }
    }
    // 实现值传递功能,也就是第一个参数onResolved不传入
    if (typeof onResolved != 'function') {
        onResolved = value => {
            return value
        }
    }


    // 使用之前的this.callbacks.push({
    // onResolved: onResolved,
    // onRejected: onRejected
    // 这样只能完成p的异步操作,因为这个新生成的Promise并没有进行改变状态
    // 因为在resolve函数中调用数组进行改变的self是指向p的
    return new Promise((resolve, reject) => {
        // 将重复部分进行封装
        function callback(type) {
            try {
                // 封装之后这里是self了,因为封装到函数里this指针指向的就是window了
                let result = type(self.promiseResult)
                if (result instanceof Promise) {
                    result.then(v => {
                        resolve(v)
                    }, r => {
                        reject(r)
                    })

                } else {
                    // 变为成功,因为return 111,或者其他都是成功
                    resolve(result);
                }
            } catch (e) {
                reject(e)
            }
        }
        // 调用回调函数
        // 这里的this指向调用者,也就是p
        // console.log(this==p);//ture
        if (this.promiseState === 'fulfilled') {
            // // 这里是同步状态下(没有定时器)改变返回的promise的状态
            // try {
            //     // 获取回调函数返回结果,是then中的匿名函数的执行结果,
            //     // console.log(111) 就是undefined,return 111 时 就是111
            //     let result = onResolved(this.promiseResult)
            //     // 判断,也就是then中的语句是返回一个promise对象,还是返回普通类型的值(比如return 111,或console.log())
            //     if (result instanceof Promise) {
            //         result.then(v => {
            //             resolve(v)
            //         }, r => {
            //             reject(r)
            //         })

            //     } else {
            //         // 变为成功,因为return 111,或者其他都是成功
            //         resolve(result);
            //     }
            // } catch (e) {
            //     reject(e)
            // }
            // 实现原版promise中的then中的回调函数是异步的
            setTimeout(() => {
                callback(onResolved)
            })

        }
        if (this.promiseState === 'rejected') {
            // try {
            //     let result = onRejected(this.promiseResult)

            //     if (result instanceof Promise) {
            //         result.then(v => {
            //             resolve(v)
            //         }, r => {
            //             reject(r)
            //         })

            //     } else {

            //         resolve(result);
            //     }
            // } catch (e) {
            //     reject(e)
            // }
            setTimeout(() => {
                callback(onRejected)
            })

        }
        // 判断pending状态,实现异步操作,比如加一个定时器
        if (this.promiseState === 'pending') {
            // 为了等异步操作结束,改变状态之后执行
            // 保存回调函数
            // console.log(self==p);//ture
            this.callbacks.push({
                onResolved: function () {
                    // // 这是异步状态下改变返回的promise的状态,
                    // // 因为异步状态下p的状态是pending,会走这个函数
                    // // 走不了上面定义好的那个resolved用来改变状态
                    // // 只能走到这里,改变状态,异步就是要用一个对象保存下来回调函数
                    // // 执行成功的回调函数,result是函数中return的东西
                    // try {


                    //     let result = onResolved(self.promiseResult)
                    //     // console.log(self == p);//ture
                    //     // 判断
                    //     if (result instanceof Promise) {
                    //         // return promise会有两种状态选择
                    //         result.then(v => {

                    //             resolve(v)
                    //         }, r => {

                    //             reject(r)
                    //         })
                    //     } else {
                    //         // 只有一种状态选择
                    //         resolve(result)
                    //     }
                    // } catch (error) {
                    //     reject(error)
                    // }
                    callback(onResolved)
                },
                onRejected: function () {
                    // try {
                    //     let result = onRejected(self.promiseResult)
                    //     // console.log(self==p);//ture
                    //     // 判断
                    //     if (result instanceof Promise) {
                    //         // return promise会有两种状态选择
                    //         result.then(v => {
                    //             resolve(v)
                    //         }, r => {
                    //             reject(r)
                    //         })
                    //     } else {
                    //         // 只有一种状态选择
                    //         resolve(result)
                    //     }
                    // } catch (error) {
                    //     reject(error)
                    // }
                    callback(onRejected)
                }

            })
        }
    })

}

// 添加catch方法
Promise.prototype.catch = function (onRejected) {
    return this.then(undefined, onRejected)
}

// 添加resolve方法,注意这个方法是构造函数的方法,而不是实例的方法
// 跟Promise中的实现then返回对象是promise,并且状态改变的那部分代码一样
Promise.resolve = function (value) {
    return new Promise((resolve, reject) => {
        if (value instanceof Promise) {
            value.then(v => {
                resolve(v)
            }, r => {
                reject(r)
            })
        } else {
            resolve(value)
        }
    })

}

// reject方法
Promise.reject = function (reason) {
    return new Promise((resolve, reject) => {
        reject(reason)
    })
}
// all方法,参数是Promise的数组
Promise.all = function (promises) {
    // 返回结果是promise对象
    return new Promise((resolve, reject) => {
        let count = 0
        // 保存结果的数组
        let arr = []
        // 遍历promise数组(参数),判断每个promise对象状态
        for (let i = 0; i < promises.length; i++) {
            // 其实一个promise对象在then中去调用resolve或reject函数
            // 修改的是这个对象的then方法返回的新promise对象的状态
            // 这里的promise[i]如果是成功的状态会走上面的函数,失败走下面的函数,这是promise对象的then方法的特性
            promises[i].then(v => {
                // 得知对象的状态是成功
                // 每个promise对象都成功
                count++
                // 还需要将每个promise对象的状态结果存入数组当中
                // 这样保证顺序不会乱
                arr[i] = v
                // 都成功
                if (count === promises.length) {
                    resolve(arr)
                }
            }, r => {
                // 有一个promise失败,则这个new Promise就是失败的
                reject(r)
            })
        }

    })

}
// race方法,谁先改变状态,返回的promise就是谁的状态
Promise.race = function (promises) {
    return new Promise((resolve, reject) => {
        for (let i = 0; i < promises.length; i++) {
            promises[i].then(v => {
                resolve(v)
            }, r => {
                reject(r)
            })
        }
    })
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值