50 handwritten line call, apply, bind method

This article is yourself some understanding of the article, with examples. To share with you
https://segmentfault.com/a/1190000020044435
Call ways:

Function.prototype.mycall = function(context,...arg){   // Function是所有函数对象的构造函数。这里给Function的原型声明了一个mycall方法,则所有的函数都拥有了这个mycall方法
    const temp = Symbol("unique symbol")  // symbol代表标识唯一性的ID(就算每次参数是unique symbol,但是temp都不相等)
    context[temp] = this   // 这里的this 代表调用mycall的函数。this的指向:被谁调用,this就指向谁。这里的context就是传递的obj2。可以理解为obj2.fn = obj1.fn
    context[temp](...arg)  // 这里通过展开运算符传递参数。展开运算符是传递参数的一种简写。调用fn函数
    delete context[temp]  // 这时将obj2.fn删除。一定要删除,因为obj2本身是没有这个函数的,只是在传递作用域调用时,做一个临时属性
}

let obj1 = {
    name: "obj1",
    fn: function(a,b,c){
        console.log(this.name+": "+ a + b + c)
    }
}
let obj2 = {
    name: "obj2",
}
obj1.fn.mycall(obj2,4,5,6)

apply ways:

Function.prototype.myApply = function (context, arg) { // apply和call实际上只有参数传递上的区别,传递的第二个参数是一个数组
    const fn = Symbol('临时属性')
    context[fn] = this
    context[fn](...arg)
    delete context[fn]
}

let obj1 = {
    name: "obj1",
    fn: function(a,b,c){
        console.log(this.name+": "+ a + b + c)
    }
}
let obj2 = {
    name: "obj2",
}
obj1.fn.myApply(obj2,[1,2,3])

bind ways:

Function.prototype.myBind = function (context, ...firstarg) {
    const that = this // 当前调用myBind的函数            
    const bindFn = function (...secoundarg) {   // bind的本质是将call方法封装成函数return 执行这个函数则调用call方法
        return that.mycall(context, ...firstarg, ...secoundarg) // 调用bind的时候可能传一次参,调用bind返回的函数可能会再一次传参。
   }
    bindFn.prototype = Object.create(that.prototype) //  复制源函数的prototype给fToBind
    return bindFn
}
let obj1 = {
    name: "obj1",
    fn: function (...arg) {
        console.log(this.name + ": " + arg)
    }
}
let obj2 = {
    name: "obj2",
}
let fnAfterBind = obj1.fn.myBind(obj2, 1, 2, 3)
fnAfterBind(4, 5, 6)
Published 51 original articles · won praise 18 · views 40000 +

Guess you like

Origin blog.csdn.net/weixin_42565137/article/details/101373857