手写call、apply、bind方法

107 阅读1分钟

call方法

call方法改变函数中this的指向,同时调用函数。

const res1 = fn.call(obj, 2,3)

===> obj.fn(2, 3) 通过调用call方法,方法内部将fn函数挂载到了obj的属性(tempFn)上,并通过obj.tempFn调用外部的fn方法,并将结果返回

Function.prototype.call = function(obj, ...args) {
    // 因为this应该指向函数的调用者,又因为fn.call()。fn调用了call方法,所以call中的this就指向fn函数
    if (obj === undefined || obj === null) 
        obj = obj || window   // 如果obj为undefined或null调用call使函数中的this指向window
    // 给obj中添加一个方法:tempFn: this
    obj.tempFn = this
    const result = obj.tempFn(...args)  // 调用fn函数并传参
    delete obj.tempFn   // 删除obj上的tempFn
    return result  // 将调用函数的返回值返回
}

apply方法

apply方法改变this执行并同时调用函数。第一个参数是函数要指向的对象, 第二个参数是一个数组。 实现方法和call类似。

Function.prototype.apply = function(obj, args) {
    if (obj === undefined || obj === null) {
        obj = obj || window
    }
    obj.tempFn = this
    const result = obj.tempFn(...args)
    delete obj.tempFn
    return result
}

bind方法

bind方法改变函数内部的this指向,同时返回一个新的函数,不改变原来的函数。

const res3 = fn.bind(obj, 2,3)(4,5)

=>const resFn = fn.bind(obj, 2, 3) const res3 = resFn(4, 5)

Function.prototype.bind = function(obj, ...args) {
    return (...args2) => {
        return this.call(obj, ...args, ...args2)
    }
}

方法测试

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <script>
        function fn(a, b) {
            console.log(a, b, this)
            return a + b
        }
       
        const res1 = fn.call(obj, 2,3) 
        console.log(res1)
        
        const res2 = fn.apply(obj, [2,9])
        console.log(res2)
        
        const res3 = fn.bind(obj, 2,3)(4,5)
        console.log(res3)
    </script>
</body>
</html>