基本使用
call、apply、bind的核心功能都是改变函数的this指向,但彼此之间也有一些差别。
call
改变this指向且执行函数,额外参数以参数列表形式传入
let context = {
name:'神秘的宝爷'
}
const myFn = function(age,height){
console.log(this.name+':'+age+':'+height)
}
myFn.call(context,25,'180cm') // 神秘的宝爷:25岁:180cm
apply
与call几乎一样改变this指向且执行函数,额外参数以数组形式传入
let context = {
name:'神秘的宝爷'
}
const myFn = function(age,height){
console.log(this.name+':'+age+':'+height)
}
myFn.call(context,[25,'180cm']) // 神秘的宝爷:25岁:180cm
bind
改变this指向,的函数,而是返回一个this被改变的function,参数以参数列表形式传入
let context = {
name:'神秘的宝爷'
}
const myFn = function(age,height){
console.log(this.name+':'+age+':'+height)
}
let myFn2 = myFn.bind(context)
myFn2(25,'180cm') // 神秘的宝爷:25岁:180cm
手动实现call、apply、bind
要实现call、apply,我们需要做两件事,第一是获取到被绑定的函数,第二就是把被绑定的函数追加到劫持替换的对象上,然后再调用追加后的函数,由于js的this指向机制是指向调用者,所以这两步实现起来似乎比较容易
我们拿call来举例:
//context就是传入的替代this的对象
Function.prototype.myCall = function(context,...params){
//当传入的替换变量不是对象的时候赋值成null
if(typeof context === "object"){
context = context || window
}else{
context = null
}
let funcName = Symbol() //使用Symbol类型定义临时方法名,避免context上的方法与临时方法重名
context[funcName] = this //获取到调用的function
context[funcName](...params)
delete context[funcName] //originFunction只是个临时属性,调用完毕后删除它
}
let context = {
name:'神秘的宝爷'
}
const myFn = function(age,height){
console.log(this.name+':'+age+':'+height)
}
myFn.myCall(context,25,'180cm') // 神秘的宝爷:25岁:180cm
实现了call之后,apply就基本实现了,只是传参方式不一样:
//context就是传入的替代this的对象
Function.prototype.myApply = function(context,params){
//当传入的替换变量不是对象的时候赋值成null
if(typeof context === "object"){
context = context || window
}else{
context = null
}
let funcName = Symbol() //使用Symbol类型定义临时方法名,避免context上的方法与临时方法重名
context[funcName] = this //获取到调用的function
context[funcName](...params)
delete context[funcName] //originFunction只是个临时属性,调用完毕后删除它
}
let context = {
name:'神秘的宝爷'
}
const myFn = function(age,height){
console.log(this.name+':'+age+':'+height)
}
myFn.myApply(context,[25,'180cm']) // 神秘的宝爷:25岁:180cm
bind实现跟上两个不太一样,但是基于上面的实现也比较简单了,因为bind不调用函数,所以我们返回一个function内部执行myCall就行了
Function.prototype.myBind = function(context){
return (...params)=>{
this.myCall(context,...params)
}
}
let context = {
name:'神秘的宝爷'
}
const myFn = function(age,height){
console.log(this.name+':'+age+':'+height)
}
const myFn2 = myFn.myBind(context)
myFn2(25,'180cm') // 神秘的宝爷:25岁:180cm