call、apply、bind

下面为了理解,我们将调用函数function称为FunA,第一个参数为context.

1、首先要明确的是: call、apply、bind是Function方法,调用call、apply、bind必须是函数.

2、call、apply、bind目的:context可以使用FunA里面的方法.

3、call、apply、bind语法

  • call语法: FunA.call(context, arg1, arg2, arg...)
  • apply语法:FunA.apply(context, [argsArray])
  • bind语法:FunA.bind(context,arg1,arg2,...)

4、call、apply、bind有什么功能?

call:

  • 改变FunA内部的this指向,使this指向context
  • arg1, arg2, arg...这种形式的参数置于实参之前传递给FunA.

apply:

  • 改变FunA内部的this指向,使this指向context
  • [argsArray]这种形式的参数置于实参之前传递给FunA.(与call的区别,参数形式不同)

bind:

  • 改变FunA内部的this指向,使this指向context
  • arg1,arg2,...这种形式的参数置于实参之前传递给FunA.
  • 返回一个函数

4、根据具体功能写call、apply、bind实现思路

  • call和apply实现思路:
    • 判断是否是函数调用,若非函数调用抛异常
    •  通过新对象(context)来调用函数
      • 给context创建一个属性fn,将fn设置为需要调用的函数.(此时被调用的函数内部this指向context,这就实现了改变this指向问题)
      • 结束调用完之后删除fn
  • bind实现思路
    • 判断是否是函数调用,若非函数调用抛异常
    • 返回函数
      • 判断函数的调用方式,是否是被new出来的
        • new出来的话返回空对象,但是实例的__proto__指向_this的prototype\
      • 完成函数柯里化
        Array.prototype.slice.call()

5、手写call、apply、bind

call:

Function.prototype.myCall = function (context) {
    // 1、判断是否是函数调用,若非函数调用抛异常
        if (typeof this !== 'function') {
           throw new TypeError("Not a Function")
        }
        // 不传参数默认为window
        context = context || window

    // 2、通过新对象(context)来调用函数
        // 给context创建一个属性fn,将fn设置为需要调用的函数.
        context.fn = this
        // 保存参数
        let args = Array.from(arguments).slice(1)   //Array.from 把伪数组对象转为数组
        let result = context.fn(...args)
        //结束调用完之后删除fn
        delete context.fn
    // 返回结果
    return result
}

apply:

Function.prototype.myApply = function (context) {
    if (typeof this !== "function") {
       throw new TypeError("Not a Function");
    }
    context = context || window;

    // 保存this
    context.fn = this;

    // 是否传参
    let result
    if (arguments[1]) {
       result = context.fn(...arguments[1]);
    } else {
       result = context.fn()
    }
    delete context.fn

    return result
}

bind:

Function.prototype.myBind = function(context){
    // 判断是否是一个函数
    if(typeof this !== "function") {
        throw new TypeError("Not a Function")
    }
    // 保存调用bind的函数
    const _this = this 
    // 保存参数
    const args = Array.prototype.slice.call(arguments,1)
    // 返回一个函数
    return function F () {
        // 判断是不是new出来的
        if(this instanceof F) {
            // 如果是new出来的
            // 返回一个空对象,且使创建出来的实例的__proto__指向_this的prototype,且完成函数柯里化
            return new _this(...args,...arguments)
        }else{
            // 如果不是new出来的改变this指向,且完成函数柯里化
            return _this.apply(context,args.concat(...arguments))
        }
    } 
}

这里bind还不够详尽,后面再重开一个,只写bind

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值