プロトタイプ



JavaScriptはプロトタイプベースの言語です.
クラスベースの言語では継承を使用しますが、プロトタイプベースの言語では、オブジェクトをプロトタイプ(prototype)としてコピー(参照)することで、継承と同様の効果が得られます.

01プロトタイプの概念を理解する


6-1-1 constructor, prototype, instance

const instance = new Constructor();
  • 新しい演算子を使用してコンストラクション関数(Constructor)を呼び出すと
  • になります.
  • Constructorで定義した内容に基づいて新しいインスタンスを作成します.
  • この場合、インスタンスは__proto__ property、
  • に自動的に付与.
  • 本番組はConstructor原型の番組を参照.
  • 整理すると、
    Constructorのプロトタイプオブジェクトの内部にインスタンスを格納する方法.
    instanceの__proto__はConstructorのprototypeを参照することを示す.
    Instanceに隠されているProperties __proto__によってConstructorのprototypeメソッドにアクセスできます.
    function Person(name) {
      this.name = name;
    }
    
    Person.prototype.getName = function () {
      return this.name;
    };
    
    const kkojae = new Person("kkojae");
    console.log(kkojae.__proto__.getName()); // undefined
    console.log(kkojae.getNmae()); // kkojae
    
    kkojae.__proto__.name = "proto-kkojae";
    console.log(kkojae.__proto__.getName()); // proto-kkojae
    上記の例では、thisバインドおよび__proto__は省略可能なpropertyであると判断することができる.
    最初のコンソールなぜlogにundefinedを出力するのですか?
  • Personでは、プロトタイプpropertyにgetNameメソッドが存在します.ただし、メソッドでは、thisバインドはthisバインドメソッド名の前のオブジェクトを使用しますが、kkojae.__proto__にはnameという値がないため、return値はthisです.nameを未定義として出力します.
  • 2番目のコンソールなぜlogにkkojaeを出力するのですか?
  • 2__proto__は省略できるので、このバインドはメソッド名の前のオブジェクトをここにバインドし、kkojaeにはgetNameというメソッドとnameというpropertyがあるので、kkojaeは通常出力されます.
  • 3番目のコンソールなぜlogにproto-kkojaeを出力しますか?
  • 最初のコンソール.ログに定義されていない正常な出力を返すために、名前のproperty値をproto-kkojaeに割り当て、getName()を呼び出します.
  • では、既存のバインディングと同様に、このバインディングはメソッド名の前のオブジェクトをこのメソッド名にバインディングし、kkojae.__proto__にはnameというpropertyとgetNameというメソッドが存在するため、nameに割り当てられたproto-kkojaeが出力される.
  • すなわち、instanceのkkojae.__proto__は省略可能なpropertyである.

    6-1-2コンストラクタ構成


    コンストラクション関数としてのprototypeオブジェクトの内部にはconstructorというpropertyがあります.コンストラクション関数呼び出しのインスタンスとしてconstructorというpropertyも存在する.
    コンストラクタは単語の意味に従って自分のプログラムを参照する.なぜコンストラクション関数propertyが存在するのですか?
  • ジェネレータ関数で呼び出されたインスタンスのプロトタイプが何であるかを決定できるからである.
  • 、すなわち、対応するインスタンスが誰から生成されたインスタンスであるかを確認することができる.
  • const arr = [1, 2];
    
    console.log(Array.prototype.constructor === Array); // true
    console.log(arr.__proto__.constructor === Array); // true
    console.log(arr.constructor === Array); // true
    
    console.log(arr instanceof Array); // true
    console.log(arr instanceof Person); // false

    6-1,6-1-2結論

  • ジェネレータ関数のプロトタイプに何らかのメソッドまたはpropertyがある場合、インスタンスでも独自のようにメソッドまたはpropertyにアクセスできます.
  • コンストラクション関数は、独自のpropertyを参照します.コンストラクション関数はinstanceofによってインスタンスが誰によって作成されたかを決定できます.
  • 02.プロトタイプチェーン


    6-2-1メソッドオーバーフロー

    function Person(name) {
      this.name = name;
    }
    
    Person.prototype.getName = function () {
      return this.name;
    };
    
    const kkojae = new Person("꼬재");
    console.log(kkojae.getName()); // 꼬재
    
    kkojae.getName = function () {
      return `내가 바로 ${this.name}}`;
    };
    
    console.log(kkojae.getName()); // 내가 바로 꼬재
    最初のコンソールロゴのkkojaegetName()は、コンストラクション関数PersonのプロトタイプメソッドgetNameです.
    2番目のコンソールロゴのkkojaegetName()kkojaeオブジェクトのgetNameメソッドを呼び出します.
    ここで,この現象をメソッドオーバーラップと呼ぶ.
    メソッドオーバーライドは、メソッドの上にメソッドがオーバーライドされていることを示します.
    ソースを削除して他のターゲットに置き換えるのではなく、オリジナルがそのままの場合、他のターゲットを上の画像に置きます.

    6-2-2プロトコルチェーン


    プロトタイプチェーンとは?
    これは、
  • のあるデータの__proto__パーセントの内部に__proto__パーセントの連鎖があることを意味する.
  • はまた、このチェーンに沿って検索することをプロトタイプチェーン(prototype chainning)と呼ぶ.
  • const arr = [1, 2];
    console.log(Array.prototype.toString.call(arr)); // 1, 2
    console.log(Object.prototype.toString.call(arr)); // [object Array]
    console.log(arr.toString()); // 1, 2
    
    arr.toString = function () {
      return this.join("__");
    };
    
    console.log(arr.toString()); // 1__2
    上記の例でarr変数の__proto____proto__を参照する.Array.prototypeがオブジェクトです.Array.prototypeを参照してください.
    すなわち,オブジェクトのtoStringはArrayのtoStringで覆われる.
    ArrはArrayのtoStringアクセスをArray.prototype.__proto__とし,toStringメソッドを用いることができる.
    ここでarrに新しいtoStringメソッドを追加すると、
    Arr.toStringはArrayのtoStringメソッドを上書きし、arrのtoStringメソッドを呼び出します.

    6-2-3対象専用メソッドの例外


    Object.Prototypeは、__proto__およびその他の参照データへの繰り返しアクセスによって達成される最高レベルであるためです.
    オブジェクト専用メソッドがObjectであることはできません.原型ではなく静的メソッドしか与えられません.
    逆に、上記の理由から、Object.プロトタイプには、任意のデータに使用できる一般的な方法があります.
    TOString、hasOwnProperty、valueOf、isPrototypeなどのすべての変数を呼び出すことができます.それは、独自の方法のようです.

    6-2-4マルチプロトコルチェーン

    __proto__が示すオブジェクトを接続すると、他の言語のクラスに似た構造を作成できます.
    すなわち,生成者関数のインスタンスを可視化すればよい.
    function Grade(...args) {
      const arr = [...args];
      // const arr = Array.prototype.slice.call(arguments);
    
      for (let i = 0; i < arr.length; i++) {
        this[i] = arr[i];
      }
    
      this.length = arr.length;
    }
    
    Grade.prototype = [];
    
    const g = new Grade(100, 80);
    
    console.log(g); // Grade(2) [100, 80]
    g.pop();
    console.log(g); // Grade [100]
    g.push(90);
    console.log(g); // Grade(2) [100, 90]

    整理する


    new演算子を使用してコンストラクション関数を呼び出すと、Constructorで定義した内容に基づいて新しいインスタンスが作成されます.
    この例は、Constructorプロトタイプpropertyを参照するproperty(__proto__)を自動的に付与する.__proto__は省略可能な属性なのでConstructor.Prototypeメソッドは、独自のメソッドを呼び出すように呼び出すことができます.
    Constructor.prototypeにはconstructorというpropertyがあり、再構築関数自体を指します.
    このプロシージャは、インスタンスが自分のコンストラクション関数が何であるかを決定するために必要な手段です.__proto__方向を探し続け、最終的にはObjectです.原型攻撃を受ける.
    このように、__proto__において__proto__を再検索するプロセスをプロトタイプフィルタと呼ぶ.
    このプロトコル・タイプ・フィルタを使用すると、各プロトコル・タイプ・メソッドを呼び出します.
    プロトタイプフィルタリングの方法は、最も近いターゲットから徐々に遠いターゲットに進み、必要な値が見つかったら検索を終了します.
    Object.Prototypeは、すべてのデータ型で使用できる一般的な方法のみを提供します.
    オブジェクト専用メソッドは、オブジェクトジェネレータ関数に静的に含まれます.
    参考書:Core JavaScript