JavaScript bind,call,apply原理,手写bind,call,apply实现

JavaScript bind,call,apply原理,手写bind,call,apply实现

1:前言

先看一个例子,一个是在全局变量中调用test函数,另一个是在people对象中调用test函数。

    var name = 'tony';
    let people = {
      name:'anny',
      test:function(){
        console.log(this.name);
      }
    }
    function test(){
      console.log(this.name)
    }
    test(); //out:tony
    people.test(); //out:anny
  • test() 输出:tony
  • people.test() 输出:anny

call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。

我们只需要模仿《在对象中调用函数》即可实现 call 与 apply。

2:实现call(实现在对象中调用函数)

    Function.prototype.myCall = function (context, ...msg) {

      //这里的 this 就是代表上面例子(前言)中的 test() 函数
      let _this = this;

      //我们需要判断一下 this 是否是一个函数,否则就抛出错误
      if (typeof _this !== 'function') {
        throw new TypeError(`${_this.name}.call is not a function`)
      }

      //获取传入的对象
      //如果没有传入对象,则取全局对象 window
      //你可以将此处的对象想象成上面例子(前言)中的 people 对象
      context = context || window;

      //将函数保存到对象的属性中
      context.test = _this;

      //获取其他传入的值
      let otherMsg = msg;

      //还记得中心思想吗?
      //实现《在对象中调用函数》
      /**
       * 如:people.test()
      */
      //这里需要记录下该函数是否有返回值
      let result = context.test(...otherMsg);

      //删除函数
      context.test = null;

      //返回函数的返回值
      return result;
    }

	test.myCall(people)

3:实现apply(实现在对象中调用函数)

    Function.prototype.myApply = function (context, msg) {

      //这里的 this 就是代表上面例子(前言)中的 test() 函数
      let _this = this;

      //我们需要判断一下 this 是否是一个函数,否则就抛出错误
      if (typeof _this !== 'function') {
        throw new TypeError(`${_this.name}.call is not a function`)
      }

      //获取传入的对象
      //如果没有传入对象,则取全局对象 window
      //你可以将此处的对象想象成上面例子(前言)中的 people 对象
      context = context || window;

      //将函数保存到对象的属性中
      context.test = _this;

      //获取其他传入的值
      let otherMsg = msg;

      //还记得中心思想吗?
      //实现《在对象中调用函数》
      /**
       * 如:people.test()
      */
      //这里需要记录下该函数是否有返回值
      let result = context.test(...otherMsg);

      //删除函数
      context.test = null;

      //返回函数的返回值
      return result;
    }

	test.myApply(people)

4:call 和 apply 的区别

apply和call差不多,只是传入的参数不同,如:

    let people1 = {
      name:'bolo'
    }
    function test1(age,sex){
      console.log(this.name);
      console.log(age);
      console.log(sex);
    }
    test1.myCall(people1,20,'男')
    test1.myApply(people1,[20,'男'])

5:实现bind(返回一个函数,调用函数时执行call,apply)

    Function.prototype.myBind = function (context, ...msg) {

      //获取函数 如:test()
      let _this = this;

      //我们需要判断一下 this 是否是一个函数,否则就抛出错误
      if (typeof _this !== 'function') {
        throw new TypeError(`${_this.name}.call is not a function`)
      }

      //返回一个函数
      return function(...msg2){

        //执行如test()函数
        //并将 test()函数返回值返回
        return _this.myCall(context,...msg,...msg2);
      }
    }
	
    /**
     * let bindF = test1.myBind(people1)
     * bindF(20,'男');
    */
	let bindF = test1.myBind(people1,20,'男')
    bindF();
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一拖再拖 一拖再拖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值