• 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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    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,'男'])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
  • 相关阅读:
    【UML】浅谈为什么要有UML?
    记一次 Visual Studio 2022 卡死分析
    ubuntn20.4安装git
    Git_03_暂存工作区的修改/自由切换分支
    【Pygame实战】打扑克牌嘛?赢了输了?这款打牌游戏,竟让我废寝忘食。
    谷歌广告推广效果不佳的原因
    C. Orac and LCM(gcd与lcm的性质)
    深度解析为什么做深度学习,都用python,而不用java或者c++
    打造千万级流量秒杀系统第四课 系统架构:如何设计秒杀的系统架构?
    面向对象05:创建对象内存分析
  • 原文地址:https://blog.csdn.net/qq_41974199/article/details/124989450