JavaScript)プロトタイプ


プロトタイプ


JavaScriptは、コマンド、関数、プロトコル・タイプに基づくオブジェクト向けプログラミングをサポートするマルチプログラミング言語です.
JavaScriptは、クラスベースのオブジェクト向けプログラミング言語に比べて、より効率的で強力なオブジェクト向けプログラミング言語です.
JAvascriptはオブジェクトベースのプログラミング言語で、javascriptを構成するほとんどの「すべて」がオブジェクトです.元のタイプの値以外の値(関数、配列、正規表現など)はオブジェクトです.

1.オブジェクト向けプログラミング


オブジェクト向けプログラミングは,実世界を認識する哲学的思考をプログラミングに導入する試みから始まった.エンティティには、エンティティを識別または区別できる特性を表す属性があります.
// 이름과 주소 속성을 갖는 객체
const person = {
	name: 'Lee',
  	address: 'Seoul'
};

console.log(person); // {name: "Lee", address: "Seoul"}
プログラマは、名前とアドレス属性で表されるオブジェクトpersonを他のオブジェクトと区別することによって識別することができる.複数の値から1単位を構成する複合材料構造をアトリビュートでオブジェクトと呼びます.
const circle = {
	radius: 5, // 반지름
  	// 원의 지름: 2r
  	getDiameter() {
    	return 2 * this.radius;
    }
}
オブジェクト向けプログラミングは、オブジェクトの状態を表すデータと、状態データを操作可能な動作とを1つの論理ユニットに組み合わせる.したがって,オブジェクトは,状態データと動作を1つの論理ユニットに組み合わせた複合データ構造といえる.このとき,オブジェクトの状態データをproperty,動作をメソッドと呼ぶ.

2.継承とプロトタイプ


継承とは、オブジェクト向けプログラミングの核心概念であり、あるオブジェクトのプログラムまたはメソッドが他のオブジェクトに継承されて使用できることを意味する.
JavaScriptはプロトコルタイプに基づいて継承を実現し,不要な重複を排除する.重複除外の方法は、既存のコードを再使用することであり、再使用は開発コストを削減する潜在力があるため、非常に重要です.
// 생성자 함수
function Circle(radius) {
	this.radius = radius;
}

// Circle 생성자 함수가 생성한 모든 인스턴스가 getArea 메서드를 공유해서 사용할 수 있도록 프로토타입에 추가
// 프로토타입은 Circle 생성자 함수의 prototype 프로퍼티에 바인딩되어 있다.
Circle.prototype.getArea = function () {
	return Math.PI * this.redius ** 2;
};

// 인스턴스 생성
const circle1 = new Circle(1);
const circle2 = new Circle(2);

// Circle 생성자 함수가 생성한 모든 인스턴스는 부모 객체의 역할을 하는
// 프로토타입 Circle.prototype으로부터 getArea 메서드를 상속받는다.
console.log(circle1.getArea === circle2.getArea); // true
Circleコンストラクション関数でgetAreaメソッドを使用する場合、関数はインスタンスを作成するたびにgetAreaメソッドを繰り返し作成し、すべてのインスタンスが繰り返し所有されます.これは、メモリを無駄にする必要がなく、同じ方法を繰り返すことを意味します.上のコードのように、継承によって不要な重複を解消することができます.JavaScriptはプロトコルタイプに基づいて継承を実現します.
コード再利用の観点から,継承は非常に有用である.コンストラクション関数で作成するすべてのインスタンスが、使用するproperty、メソッドをprototypeに事前に実装している場合、作成するインスタンスは、親オブジェクトprototypeの資産を共有できます.

3.プロトタイプオブジェクト


prototypeオブジェクトは、オブジェクトプログラミングベース向けのオブジェクト間の継承を実現するために使用されます.プロトコルタイプは、オブジェクトの親としてのオブジェクトであり、他のオブジェクトに共有プロトコルを提供します.基本タイプを継承したサブオブジェクトは、自分の基本タイプを使用するように親オブジェクトの基本タイプを自由に使用できます.
たとえば、オブジェクトテキストから作成されたオブジェクトのプロトタイプはObjectです.プロトタイプ、コンストラクション関数によって生成されたオブジェクトのプロトタイプがコンストラクション関数のプロトタイププロトタイプのオブジェクトにバインドされます.
各オブジェクトにはプロトタイプがあります.また,すべてのプロトタイプは構造関数に関連付けられている.
[Prototype]の内部スロットに直接アクセスすることはできませんが、__proto__のアクセス者propertyを使用して、独自のプロトタイプ、すなわち[Prototype]の内部スロットが指すプロトタイプに間接的にアクセスできます.

3-1. __protoビジターProperty


すべてのオブジェクトは、__proto__のビジタープログラムを使用して、独自のプロトタイプの内部スロットに間接的にアクセスできます.
  • __proto__は、訪問者プログラムである.
    原則として、JavaScriptは内部スロットと内部メソッドに直接アクセスまたは呼び出す方法を提供しません.ただし,一部の内部スロットと内部メソッドに限られ,間接アクセスの手段が提供される.[prototype]内部スロットの値、すなわちprototypeには、__proto__アクセス者propertyによって間接的にアクセスできます.
  • __proto__訪問者propertyは継承によって使用される.__proto__ビジターPropertyは、オブジェクトが直接所有するPropertyではなく、Objectです.プロトタイプのproperty.すべてのオブジェクトは、Object.prototype.__proto__アクセス者プログラムを継承することによって使用することができる.
    const person = { name: 'Lee' };
    
    // person 객체는 __proto__ 프로퍼티를 소유하지 않는다.
    console.log(person.hasOwnProperty('__proto__')); // false
    
    // __proto__ 프로퍼티는 모든 객체의 프로토타입 객체인 Object.prototype의 접근자 프로퍼티다.
    console.log(Object.getOwnPropertyDescriptor(Object.prototype, '__proto__'));
    // {get: f, set: f, enumerable: false, configurable: true}
    
    // 모든 객체는 Object.prototype의 접근자 프로퍼티 __proto__를 상속받아 사용할 수 있다.
    console.log({}.__proto__ === Object.prototype); //true
  • __proto__ビジターPropertyを介してプロトコル・タイプにアクセスする理由
    [PRODototype]の内部スロットの値、すなわちプロトコルタイプにアクセスするには、相互参照によるプロトコルタイプチェーンの生成を防止するために、アクセス者propertyを使用します.
    const parent = {};
    const child = {};
    
    // child의 프로토타입을 parent로 설정
    child.__proto__ = parent;
    // parent의 프로토타입을 child로 설정
    parent.__proto__ = child; // TypeError: Cyclic __proto__ value
    上記の例では、互いにプロトコルタイプに設定されていますが、親プロトコルの設定中にエラーが発生しました.これらのコードが正常に処理されると、互いに写真の原型となる非正常な原型チェーンが生成されるため、__proto__訪問者の原型にエラーが発生する.
    プロトタイプチェーンは一方向チェーンテーブルとして体現されるべきである.互いに持つプロトコルタイプの非正常なチェーンが作成されると、プロトコルタイプチェーンでプロトコルを検索すると無限ループに陥ります.したがって、__proto__アクセス者プロトコルによってプロトコルタイプにアクセスおよび置換され、チェックを必要としない.

  • コードに__proto__アクセス者プロパティを直接使用することは推奨されません.
    すべてのオブジェクトが__proto__アクセス者プロパティを使用できるわけではありません.直接継承オブジェクト:プロトタイプを継承しないオブジェクトを生成できるため、__proto__アクセス者構成を使用できない場合があります.
    // obj는 프로토타입 체인의 종점이다. 따라서 Object.__proto__를 상속받을 수 없다.
    const obj = Object.create(null);
    
    // obj는 Object.__proto__를 상속받을 수 없다.
    console.log(obj.__proto__); // undefined
    
    // 따라서 __proto__보다 Object.getPrototypeOf 메서드를 사용하는 편이 좋다.
    console.log(Object.getPrototypeOf(obj)); // null
    したがって、__proto__のビジター・プロパティではなく、プロトコル・タイプの参照を取得する場合は、「Object」を選択します.getPrototypeOfメソッドを使用してプロトタイプを置き換えたい場合は、「Object」を選択します.setPrototypeOfメソッドの使用を推奨します.これにより、ES 6に導入された方法は、多くないIE 11以降でサポートされる.
  • 3-2. 関数オブジェクトのプロトタイプ構成


    関数オブジェクトのみが持つprototypeとは、コンストラクション関数によって作成されるインスタンスのタイプです.
    prototype propertyとは、コンストラクション関数によって生成されるオブジェクトのタイプを指します.したがって,コンストラクション関数として呼び出すことができない関数,非コンストラクション関数矢印関数,ES 6メソッドサムネイルによって定義されるメソッドはプロトタイプPropertyを持たず,プロトタイププロトタイプも作成しない.
    すべてのオブジェクトが所有する(object.prototypeから継承された)__proto__アクセス者propertyと、関数オブジェクトのみが所有するプロトタイプpropertyは、最終的に同じprototypeを指します.しかし、これらの番組を使う主体は違います.

    3-3. 基本タイプのコンストラクション関数の基本情報とコンストラクション関数


    すべてのプロトコルタイプには、コンストラクション関数プロトコルがあります.このコンストラクション関数propertyは、そのコンストラクション関数を参照するプロトタイプpropertyです.この接続は、コンストラクション関数の作成時(つまり、関数オブジェクトの作成時)に行われます.
    // 생성자 함수
    function Person(name) {
    	this.name = name;
    }
    
    const me = new Person('Lee');
    
    // me 객체의 생성자 함수는 Person이다.
    console.log(me.constructor === Person); // true
    モダンJavaScript Deep Diveを読んでまとめた文章.😊