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)