call、apply、bind使用与内部实现

基本使用

call、apply、bind的核心功能都是改变函数的this指向,但彼此之间也有一些差异。数组

call

改变this指向且执行函数,额外参数以参数列表形式传入app

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,参数以参数列表形式传入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、bind

要实现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


复制代码
相关文章
相关标签/搜索