大家都知道call,apply,bind,都是改变this 指向,具体怎么实现的,先来看看代码
let person={
getName:function(){
return this.name
}
}
let man={
name:"张三"
}
// 先执行一下getName函数,但是它里边没有name这个属性,所以打印出来是undefied
console.log(person.getName())
//如果想把man里边的name给getName的话,这时我们可以用call改变this指向
console.log(person.getName.mycall(man))
那call具体是在哪里呢,此时我们去打印一下它的原型对象。
console.log(person.getName.prototype)
//打印台的显示
1. {constructor: ƒ}
1. 1. constructor: ƒ ()
1. 1. arguments: null
1. caller: null
1. length: 0
1. name: "getName"
1. prototype: {constructor: ƒ}
1. [[FunctionLocation]]: 1.html:17
1. [[Prototype]]: ƒ ()
1. 1. apply: ƒ apply()
1. arguments: (...)
1. bind: ƒ bind()
1. call: ƒ call()
1. caller: (...)
1. constructor: ƒ Function()
1. length: 0
1. name: ""
1. toString: ƒ toString()
1. Symbol(Symbol.hasInstance): ƒ [Symbol.hasInstance]()
1. get arguments: ƒ ()
1. set arguments: ƒ ()
1. get caller: ƒ ()
1. set caller: ƒ ()
1. [[FunctionLocation]]:
1. [[Prototype]]: Object
1. [[Scopes]]: Scopes[0]
1. [[Scopes]]: Scopes[2]
1. [[Prototype]]: Object
打印出来可以看到call是挂载到原型对象上边的,所以要实现这个功能,我们也要在原型上边挂载一个方法。 现在来手写一个call,先在原型上挂载一个MyCall的方法。 此时的this指向的是person.getName,因为是person.getName调用的,并且这边有两个条件,this必须是个函数,而且必须要传值,不传的话默认是window。
Function.prototype.mycall=function(man){
// 第一步先去调用getName函数,并将this指向getName函数
const res=this()
return res
}
console.log(person.getName.mycall(man))
此时getName函数的this指向的是this,那怎么让this指向man呢?
Function.prototype.mycall=function(man){
// 假设man上边有个函数,用this把它替换掉,此时指向的就是man了
man.fn=this
const res=man.fn()
return res
}
console.log(person.getName.mycall(man))
手写call基础完成,关于涉及的this指向的知识点没有详细讲解,有需要改进的点欢迎多多留言