手写源码

97 阅读1分钟

闭包

-可以在另一个作用域中调用函数的内部函数并访问到该函数的作用域中的成员
function once(fn) {
    let done = false
    return function () {
        if (!done) {
            done = true
            return fn.apply(this, arguments)
        }
    }
}

let pay = once(() => {
    console.log(5)
})

memoize 缓存结果

function memoize (f){
    let catch = {} 
    return function (){ 
        let key = JSON.stringify(arguments)
        catch[key] = catch[key] || f.apply(f,arguments) 
        return catch[key] 
    } 
}

done 函数只执行一次

function done(fn){
    let done = false 
    return function (){ 
        if(!done){ 
            done = true 
            return fn.apply(this,arguments) 
       } 
   } 
}

curry 函数的柯里化

-当一个函数具有多个参数的时候,先传递一部分参数调用他(这部分参数以后永远不变)
-然后返回一个新的函数接受剩余的参数,返回结果
 const currys = func => {
        return curriedFn = (...args) => {
            //判断实参和行参的个数是否相等
            if (args.length < func.length) {
                return function () {
                    return curriedFn(...args.concat(Array.from(arguments)))
                }
            }
            return func(...args)
        }
    }

    const getNum = (a, b, c) => {
        return a + b + c
    }

    let curried = currys(getNum)
    console.log(curried(1)(2)(3, 4))

flowRight 函数组合

-如果一个函数要经过多个函数处理才能得到最终值,这个时候可以把中间过程的函数合并成一个函数
-函数就像是数据的管道,函数组合就是把这些管道连接起来,让数据穿过多个管道形成最终结果
-函数组合默认是从右到左执行
// const _ = require('loadsh')
//模拟loadsh的flowRight函数
const flowRight = (...args) => value => args.reverse().reduce((acc, fn) => fn(acc), value)

const reverse = arr => arr.reverse()
const first = arr => arr[0]
const toUpper = s => s.toUpperCase()


const compose = flowRight(toUpper, first, reverse)
console.log(compose(['asd', 'hgds', 'uygkjn']))

react hooks中实现函数节流

//函数节流
const useThrottle = (fn: any, delay: number, dep = []) => {
    const { current } = useRef({ fn, timer: null as unknown });
    useEffect(
        function () {
            current.fn = fn;
        },
        [fn],
    );

    return useCallback(function f(...args) {
        if (!current.timer) {
            current.timer = setTimeout(() => {
                delete current.timer;
            }, delay);
            current.fn.call(current, ...args);
        }
    }, dep);
};