JavaScript bind()方法の実現


方法の特徴
  • bit()メソッドは新しい関数を作成します.
  • この新しい関数が呼び出されると、bind()の最初のパラメータが動作するときのthisとなります.
  • は、最初のパラメータ以外の他のパラメータを下の階層の関数(この技術を「部分的応用」と呼び、「コリゼーション」の一種)に渡すことができます.注①
  • は、ビン()が返した関数をコンストラクタとして使用すると、ビン時に指定されたthis値が無効になりますが、入力されたパラメータは有効です.
  • new呼び出しが返された例は、バインディング関数のプロトタイプの値
  • を継承することができる.
    注①:
  • 「あなたが知らないJavaScript」
  • から来ました.
  • 局部応用とコリゼーションについては、mqgingfengを参照してください.
  • コリック化は、一つの多パラメータ関数を複数の単一パラメータ関数、すなわち一つのn要素関数をn個の一要素関数に変換することである.
  • ローカルアプリケーションは、1つの関数を固定する1つまたは複数のパラメータ、すなわち1つのn要素関数を1つのn−x要素関数に変換することである.
  • 両者の関係について言えば、functionl-programming-jargonの記述を参照してください.Curied functions are autically partially aplied.
  • ビッド()実現
    方法1
    Function.prototype.fakeBind = function(context) {
      if (typeof this !== "function") {
        throw new Error("Bind must be called on a function");
      }
      let self = this;
      //               
      let args = Array.prototype.slice.call(arguments, 1);
    
      let inner = function() {
        //                
        let innerArgs = Array.prototype.slice.call(arguments);
        // 1 new    ,this     。   bind      this       ;
        // 2    instanceof          true、false,      new   ;
        // 3          this       。        this    
        return self.apply(
          this instanceof inner ? 
          this : 
          context, args.concat(innerArgs)
        );
      };
      // inner.prototype = this.prototype 
      //         ,           (inner.prototype)              (this.prototype)      。
      //         ,this.protptype     。           。
      // ②
      let fNOP = function() {};
      fNOP.prototype = this.prototype;
      inner.prototype = new fNOP();
      return inner;
    };
    注②
    fno.prototype=this.prototype;つまり、this.prototypeの原型の対象となるfno.prototypeとfno.prototypeは同じ対象を指します.
    var f=new fNOP()のように;その後、プロトタイプチェーンの属性を探します.f.protoを通して、
    f.proto==fno.prototype==this.prototype
    this.prototypeに属性を探しに行きます.
    方法二ES 6版
    Function.prototype.fakeBindES6 = function(context, ...rest) {
      if (typeof this !== "function") {
        throw new Error("Bind must be called on a function");
      }
      var self = this;
      return function inner(...args) {
        if (this instanceof inner) {
          //                 ,bind      this   。
          //            ,     apply   this      
          return new self(...rest, ...args);
        }
        //          ,this        
        return self.apply(context, rest.concat(args));
      };
    };
    参考:https://github.com/mqyqingfeng/Blog/issues/12