JS bind()方法、JS原生实现bind()

作者: puxiaotaoc | 来源:发表于2018-09-09 00:50 被阅读89次
    一、arguments的含义
    // arguments 是一个对应于传递给函数的参数的类数组对象
      function a(){
        console.log(arguments);
      }
      a(); // Arguments [callee: ƒ, Symbol(Symbol.iterator): ƒ]
      a(1,2,3); // Arguments(3) [1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]
    
    二、Function.prototype.bind()

           bind()方法主要就是将函数绑定到某个对象,bind()会创建一个函数,函数体内的this对象的值会被绑定到传入bind()中的第一个参数的值,例如:f.bind(obj),实际上可以理解为obj.f(),这时f函数体内的this自然指向的是obj;

      var a = {
        b: function() {
          var func = function() {
            console.log(this.c);
          }
          func();
        },
        c: 'hello'
      }
      a.b(); // undefined 这里的this指向的是全局作用域
      console.log(a.c); // hello
    
      var a = {
        b: function() {
          var _this = this; // 通过赋值的方式将this赋值给that
          var func = function() {
            console.log(_this.c);
          }
          func();
        },
        c: 'hello'
      }
      a.b(); // hello
      console.log(a.c); // hello
    
    // 使用bind方法一
      var a = {
        b: function() {
          var func = function() {
            console.log(this.c);
          }.bind(this);
          func();
        },
        c: 'hello'
      }
      a.b(); // hello
      console.log(a.c); // hello
    
    // 使用bind方法二
      var a = {
        b: function() {
          var func = function() {
            console.log(this.c);
          }
          func.bind(this)();
        },
        c: 'hello'
      }
      a.b(); // hello
      console.log(a.c); // hello
    
    // 分析:这里的bind方法会把它的第一个实参绑定给f函数体内的this,所以里的this即指向{x:1}对象;
    // 从第二个参数起,会依次传递给原始函数,这里的第二个参数2即是f函数的y参数;
    // 最后调用m(3)的时候,这里的3便是最后一个参数z了,所以执行结果为1+2+3=6
    // 分步处理参数的过程其实是一个典型的函数柯里化的过程(Curry)
      function f(y,z){
        return this.x+y+z;
      }
      var m = f.bind({x:1},2);
      console.log(m(3)); // 6
    
    // 分析:直接调用a的话,this指向的是global或window对象,所以会报错;
    // 通过bind或者call方式绑定this至document对象即可正常调用
      var a = document.write;
      a('hello'); // error
      a.bind(document)('hello'); // hello
      a.call(document,'hello'); // hello
    
    // 实现预定义参数
    // 分析:Array.prototype.slice.call(arguments)是用来将参数由类数组转换为真正的数组;
      function list() {
        return Array.prototype.slice.call(arguments);
      }
      var list1 = list(1, 2, 3); // [1,2,3]
    // 第一个参数undefined表示this的指向,第二个参数10即表示list中真正的第一个参数,依次类推
      var a = list.bind(undefined, 10);
      var list2 = a(); // [10]
      var list3 = a(1, 2, 3); // [10,1,2,3]
    
    三、原生js实现bind方法
    // 方法一,只可绑定,不可传参
      Function.prototype.my_bind = function(context){
        var self = this;
        return function(){
          self.apply(context,arguments);
        }
      }
      function a(){
        console.log(this.name);
      }
      a();  // ''
      var b = {
        name: 'apple'
      };
      a.bind(b)(); // apple
      a.my_bind(b)(); // apple
    
       Function.prototype.my_bind = function() {
          var self = this, // 保存原函数
            context = Array.prototype.shift.call(arguments), // 保存需要绑定的this上下文
            // 上一行等价于 context = [].shift.call(arguments);
            args = Array.prototype.slice.call(arguments); // 剩余的参数转为数组
          return function() { // 返回一个新函数
            self.apply(context, Array.prototype.concat.call(args, Array.prototype.slice.call(arguments)));
          }
        }
    
      function a(m, n, o) {
        console.log(this.name + ' ' + m + ' ' + n + ' ' + o);
      }
    
      var b = {
        name: 'kong'
      };
    
      a.my_bind(b, 7, 8)(9); // kong 7 8 9
    

    参考链接:
    JS中的bind()方法
    js中自己实现bind函数的方式

    相关文章

      网友评论

        本文标题:JS bind()方法、JS原生实现bind()

        本文链接:https://www.haomeiwen.com/subject/aezlgftx.html