マスターオブジェクト🍨 第2部



オブジェクトとプロトタイプ
多くのオブジェクト指向言語のように、JavaScriptは実装継承のサポートを提供します:ダイナミックな委任メカニズムを通してコードまたはデータの再利用.しかし、多くの従来の言語とは異なり、JavaScriptの継承メカニズムはクラスよりむしろプロトタイプに基づいています.多くのプログラマにとって、JavaScriptはクラスなしで遭遇する最初のオブジェクト指向言語です.
多くの言語では、すべてのオブジェクトは関連するクラスのインスタンスです.そして、それはすべてのそのインスタンスの間で共有されるコードを提供します.JavaScriptは対照的に、クラスの組み込み概念を持っていません.代わりに、オブジェクトは他のオブジェクトから継承します.すべてのオブジェクトは、そのプロトタイプとして知られているいくつかの他のオブジェクトに関連付けられています.伝統的なオブジェクト指向言語からの多くの概念がまだ引き継ぐけれども、プロトタイプで働くことはクラスと異なることができます.

違いを理解するprototype , getPrototypeOf and __proto__プロトタイプは3つの別々であるが関連したアクセッサを含んでいます.この不幸な重なりは、かなりの混乱に自然につながる.要点をまっすぐにしましょう.
  • C.prototype はnew C ()が作成したオブジェクトのプロトタイプを確立するために使用されます.
  • Object.getPrototypeOf(obj) 検索のための標準ES 5メカニズムobj ’sプロトタイプオブジェクト.
  • obj.__proto__ 検索のための非標準メカニズムobj ’sプロトタイプオブジェクト
  • これらの各々を理解するために、JavaScriptデータ型の典型的な定義を考えてください.ユーザコンストラクターは新しい演算子で呼び出され、パスワード文字列と
    そのオブジェクトを作成します.
    function User(name, passwordHash) {
      this.name = name;
      this.passwordHash = passwordHash;
    }
    
    User.prototype.toString = function () {
      return "[User " + this.name + "]";
    };
    
    User.prototype.checkPassword = function (password) {
      return hash(password) === this.passwordHash;
    };
    
    let u = new User("sfalken", "0ef33ae791068ec64b502d6cb0191387");
    
    ユーザー関数には、既定のプロトタイププロパティが付属しており、空または複数の空を開始するオブジェクトが含まれます.この例では、User.prototype 対象:toString and checkPassword. 新しい演算子を使用してユーザーのインスタンスを作成すると、結果のオブジェクトUはUser.prototype自動的にプロトタイプオブジェクトとして割り当てられます.下の画像は、これらのオブジェクトの図を示します
    インスタンスオブジェクトUをプロトタイプオブジェクトにリンクしている矢印に注目してくださいUser.prototype . このリンクは継承関係を示します.
    プロパティの検索はobject ’s own properties ; 例えば、米国の名前とu.passwordHash uに直接見つからないUプロパティの即時プロパティの現在の値をUのプロトタイプで調べます.アクセスu.checkPassword , たとえば、User.prototype .
    これは私たちのリストの次の項目につながる.コンストラクタ関数のプロトタイププロパティを使用して、新しいインスタンスのプロトタイプ関係を設定しますObject.getPrototypeOf()
    既存のオブジェクトのプロトタイプを取得するために使用します.したがって、例えば、上記の例でオブジェクトUを作成した後にテストすることができます.
    Object.getPrototypeOf(u) === User.prototype; // true
    

    This illustrates the prototype relationships for the User constructor and
    instance.


    いくつかの環境は検索のための非標準メカニズムを生成する
    特別なものを通しての物体の原型__proto__ プロパティ.これは
    ES 5のサポートしていない環境のための一時停止として役に立つObject.getPrototypeOf . このような環境では、同様にテストすることができます.
    u.__proto__ === User.prototype; // true
    
    プロトタイプの関係についての最終的な注意:JavaScriptプログラマは、しばしば、それが機能より少し多くであるとしても、クラスをクラスとして説明するでしょう.JavaScriptのクラスは、基本的にコンストラクタ関数(ユーザ)とクラスのインスタンス間でメソッドを共有するために使用されるプロトタイプオブジェクトの組み合わせですUser.prototype ).

    This is a conceptual view of the User “class”.


    上記のイメージは、ユーザークラスを概念的に考える良い方法を提供します.ユーザー関数は、クラスのパブリックコンストラクターを提供しますUser.prototype インスタンス間で共有されるメソッドの内部実装です.ユーザーとUの通常の使用は、直接プロトタイプオブジェクトにアクセスする必要はありません.

    覚えていること🧠
  • C.prototype 新しく作成したオブジェクトのプロトタイプを決定するC() .
  • Object.getPrototypeOf(obj) オブジェクトのプロトタイプを取得するための標準ES 5関数です.
  • obj.__proto__ オブジェクトのプロトタイプを取得するための非標準メカニズムです.
  • クラスは、コンストラクタ関数と
    関連プロトタイプ.

  • 好むObject.getPrototypeOf to __proto__ 🦄
    ES 5導入Object.getPrototypeOf オブジェクトのプロトタイプを検索するための標準APIとして、JavaScriptエンジンの多くの後にのみ__proto__ 同じ目的のプロパティ.しかし、すべてのJavaScript環境がこの拡張モジュールをサポートしているわけではない.環境は、例えば、ヌルプロトタイプを有するオブジェクトの処置に関して異なる.いくつかの環境ではObject.prototype , したがって、nullプロトタイプを持つオブジェクトには特別なPropertyプロパティはありません.
    var empty = Object.create(null); // object with no prototype
    "__proto__" in empty; // false (in some environments)
    // In  others,  __proto__  is  always  handled  specially,  regardless  of  an object’s state:
    
    var empty = Object.create(null); // object with no prototype
    "__proto__" in empty; // true (in some environments
    
    どこObject.getPrototypeOf 利用可能な、それはプロトタイプを抽出するためのより標準的でポータブルなアプローチです.また、__proto__ プロパティは、その汚染のためにバグの数につながる
    すべてのオブジェクト.現在拡張機能をサポートしているJavaScriptエンジンは、これらのバグを避けるために、プログラムを無効にすることを将来的に選ぶかもしれません.好むObject.getPrototypeOf コードが動作し続けても、__proto__ 無効です.
    ES 5 APIを提供しないJavaScript環境のために、それは4の条件で実装するのが簡単です__proto__ :
    if (typeof Object.getPrototypeOf === "undefined") {
      Object.getPrototypeOf = function (obj) {
        var t = typeof obj;
        if (!obj || (t !== "object" && t !== "function")) {
          throw new TypeError("not an object");
        }
        return obj.__proto__;
      };
    }
    

    This implementation is safe to include in ES5 environments, because it avoids installing the function if Object.getPrototypeOf already exists.



    覚えていること🧠
  • 標準準拠Object.getPrototypeOf
    標準__proto__ プロパティ.
  • 実装Object.getPrototypeOf 非ES 5環境で
    サポート__proto__ .

  • 修正する__proto__ 🍕
    特別なProtoプロパティは、追加のパワーを提供しますObject.getPrototypeOf オブジェクトのプロトタイプリンクを変更する機能.この力は無邪気に見えるかもしれませんが(結局のところ、それはちょうど別の財産です.)それは実際に重大な意味を持ち、避けなければならない.変更を避ける最も明白な理由__proto__ 移植性はすべてのプラットフォームでサポートされています
    オブジェクトのプロトタイプを変更するだけで、それを行うポータブルコードを書くことができません.
    変更を避けるもう一つの理由__proto__ パフォーマンスです.JavaScriptプログラムは、JavaScriptプログラムが実行する最も一般的な操作のいくつかであるので、すべての最新のJavaScriptエンジンは、オブジェクトプロパティの取得および設定の方法を大きく最適化します.これらの最適化は、オブジェクトの構造のエンジンの知識に基づいて構築されます.オブジェクトの内部構造を変更すると、オブジェクトまたはオブジェクトにそのプロパティを追加または削除することによって、そのプロトタイプのチェーン内のオブジェクトを変更すると、これらの最適化の一部が無効になります.修飾__proto__ 実際に継承構造自体を変更します.これは通常のプロパティへの変更よりも多くの最適化を無効にすることができます.
    しかし、修正を避ける最大の理由__proto__ 予測可能な動作を維持するためです.オブジェクトのプロトタイプチェーンは、プロパティとプロパティ値の集合を決定することによってその動作を定義します.オブジェクトのプロトタイプリンクを変更することは、それに脳移植を与えるようです.そのような操作が役に立つかもしれない例外的な状況を想像することは可能かもしれません、しかし、基本的な健全性の問題として、継承階層は安定していなければなりません.
    カスタムプロトタイプリンクを使用して新しいオブジェクトを作成するにはObject.create . ES 5を実装しない環境のために、アイテム33はポータブルObject.create それは当てにならない__proto__ .

    覚えていること🧠
  • オブジェクトを変更しない__proto__ プロパティ.
  • 用途Object.create 新しいオブジェクトのカスタムプロトタイプを提供します.

  • 🎉🎉🎉 この記事の第2部を読んでくれてありがとう!🎉🎉🎉

    このSERIEの3番目の部分をチェックアウトすることを忘れないでください!🥳 Make your Constructors new-Agnostic .
    あなたの好きなプログラミング言語についての深さの知識の詳細についてはblog オンデマンド開発者になる😉, そして、あなたは同様に私を見つけることができます😃.