call、apply、bind的核心功能都是改变函数的this指向,但彼此之间也有一些差异。数组
改变this指向且执行函数,额外参数以参数列表形式传入app
let context = {
name:'神秘的宝爷'
}
const myFn = function(age,height){
console.log(this.name+':'+age+':'+height)
}
myFn.call(context,25,'180cm') // 神秘的宝爷:25岁:180cm
复制代码
与call几乎同样改变this指向且执行函数,额外参数以数组形式传入函数
let context = {
name:'神秘的宝爷'
}
const myFn = function(age,height){
console.log(this.name+':'+age+':'+height)
}
myFn.call(context,[25,'180cm']) // 神秘的宝爷:25岁:180cm
复制代码
改变this指向,的函数,而是返回一个this被改变的function,参数以参数列表形式传入ui
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,咱们须要作两件事,第一是获取到被绑定的函数,第二就是把被绑定的函数追加到劫持替换的对象上,而后再调用追加后的函数,因为js的this指向机制是指向调用者,因此这两步实现起来彷佛比较容易this
咱们拿call来举例:spa
//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就基本实现了,只是传参方式不同:prototype
//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就好了code
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
复制代码