Skip to content
On this page

手写 call、apply 及 bind 函数

call

js
Function.prototype._call = function(context, ...args) {
    if (typeof this !== 'function') {
        throw new TypeError('Error')
    }
    context = context || window
    args = args ? args : []
    //给context新增一个独一无二的属性以免覆盖原有属性
    const key = Symbol()
    context[key] = this
    //通过隐式绑定的方式调用函数
    const result = context[key](...args)
    delete context[key]
    return result
}

apply

js
Function.prototype._apply = function(context, args) {
    if (typeof this !== 'function') {
        throw new TypeError('Error')
    }
    context = context || window
    args = args ? args : []
    //给context新增一个独一无二的属性以免覆盖原有属性
	const key = Symbol()
    context[key] = this
    let result
    //通过隐式绑定的方式调用函数
    const result = context[key](...args)
    delete context[key]
    return result
}

bind

js
Function.prototype._bind = function(context, ...args) {
    if(typeof this !== 'function'){
        throw '请使用函数调用'
    }
    const fn = this
    context = context || window
    args = args ? args : []
    return function newFn(...rest) {
        // 如果bind返回的那个函数是被new调用,this应指向返回的那个函数。
        if (this instanceof newFn) {
            return new fn(...args, ...rest)
        }
        return fn.call(context, ...args, ...rest)
    }
}

区别

  • call、apply、bind都将this指向绑定到第一个参数,第一个参数是null / undefined,等同于指向全局对象

  • call、apply会立即执行函数,区别是apply的第二个参数是函数执行时的参数的数组,而call是单个传入

  • bind返回的是一个绑定了this指向的函数

Released under the MIT License.