聊一聊call、apply、bind

148 阅读2分钟

call、apply、bind用法及不同点

- 相同点:
    1. call、apply、bind都是Function原型上的方法,所有的函数都可以调用这三个方法 
    2. call、apply、bind都能将调用该方法的函数中的this指向该方法的第一个参数
    3. call、apply方法能在改变this指向的同时,执行调用者函数
- 不同点
    1. call、apply会调用函数,而bind不会,bind会返回一个和调用者函数一样的函数
    2. call和bind会将第二个及后面的所有参数传递进调用者函数内,而apply的第二个参数为数组,调用apply时,会先将该数组展开,然后传入调用者函数
 //call
Function.prototype.myCall = function(o,...rest){
    //当o为undefined或null时,函数调用后的this指向window
    if(o===null||o===undefined){
        o = window
    }
    //如果o是基本数据类型,则this指向其包装对象(Number、String、Boolean)
    if(typeof o !== 'function' && typeof o !== 'object'){
        o = Object(o)//Object可以将一个基本数据类型转换为包装对象
    }
    //当o不满足以上五种情况时,this应该指向o
    const msg = Symbol('msg')//创建一个唯一的属性,用来存放this
    o[msg] = this//原型对象上的方法,this一定指向实例对象
    //调用该方法,形参...rest为获取所有传递进来的参数
    const res = o[msg](...rest)//调用时的...rest为展开rest并作为实参传入
    //res即是call调用该函数的返回值,调用完后删除该属性
    delete o[msg]
    //将res返回
    return res
}
apply方法和call类似,因为apply第二个参数为一个数组,则形参不需要用...rest接收,直接定义一个形参接收数组即可

//bind
Function.prototype.myBind = function(){
    //获取外部函数的this,也就是调用者
    const _this = this
    //获取实参列表
    const args = Array.from(arguments)
    //bind会返回一个函数
    return function(){
        //函数的返回值就是外部this,也就是调用者的返回值,这里偷懒直接用apply调用了,面试如果规定不能用就只能再写一遍apply了
        return _this.apply(args[0],args.slice(1))
    }
}
欢迎补充^ ^