Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

快速手写一遍 call、apply、bind #6

Open
HardenSG opened this issue May 6, 2023 · 0 comments
Open

快速手写一遍 call、apply、bind #6

HardenSG opened this issue May 6, 2023 · 0 comments

Comments

@HardenSG
Copy link
Owner

HardenSG commented May 6, 2023

1. call:

call() 方法在使用一个指定的 this 值和若干个指定的参数值的前提下调用某个函数或方法。

const isFunc = v => typeof v === 'function'

Function.prototype.customCall = function(context) {
    if(!isFunc(this)) {
        return undefined
    }

    /** ensure fn is a unique property in context */
    const fn = Symbol()
    
    /** mount this 'fn' property to context object */
    context = context || globalThis
    context[fn] = this 

    /** splice arguments */
    const args = [...arguments].slice(1)

    /** call this function */
    const res = context[fn](...args)

    /** delete this property in this context object */
    delete context[fn]

    return res
}

2. apply

call 方法的区别就是参数的传递方式,apply 函数的参数传递方式是以数组形式的

Function.prototype.customApply = function(context) {
    if(!isFunc(this)) {
        return undefined
    }

    const fn = Symbol()
    context = context || globalThis

    context[fn] = this 

    const args = [...arguments].slice(1)
    const res = context[fn](args)

    delete context[fn]
    return res
}

3. bind

bind方法可以用来做函数的柯里化,对于函数中同时存在确定和不确定的入参,可以先使用bind 函数将确定的那一部分入参固定,比如

const request = (id, msg) => {
    axios({
        url: '...',
        data: {
            id, 
            msg
        }
    })
}

// 对于 id 可能进入当前路由就已经确定,msg是不确定的
// 所以可以先使用柯里化将其固定住
const sendFunc = request.bind(null, id)

// 后续使用
sendFunc(msg)

所以可以这样写

Function.prototype.customBind = function(context) {
    if(!isFunc(this)) {
        return undefined
    }

    const fn = this 
    const args = [...arguments].slice(1)

    /** 'bind' function need return a function */
    /** and simultaneity, you can change this context object become a 'Fn''s instance */
    /** beside args, you can pass other params for call this function */
    return function Fn() {
        return fn.apply(
            this instanceof Fn ? this : context,
            args.concat(arguments)
        )
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant