ECMAScript作成対象2——原型モード


  • プロトタイプオブジェクトの概念ECMAScriptにおいて、ユーザは新しい関数を作成するごとに、この関数のセットに対してプロトタイプ属性を作成します.プロトタイプ属性はこの関数のプロトタイプオブジェクトを指しています.このプロトタイプオブジェクトはこの関数のすべてのインスタンスに共有される属性と方法を含んでいます.ここでは,構造関数モードに存在する最大の問題を解決した.
  • 構築関数、プロトタイプオブジェクト、インスタンス間の関係
  • コンストラクションのprototype属性はプロトタイプオブジェクトを指し、プロトタイプオブジェクトのconstructor属性はコンストラクタを指す.
  • 例のポインタがプロトタイプのオブジェクトを指しています.ECMA-262第5版の中で「プロトタイプ」といいます.Firefox、rmche、Safariブラウザでは、インスタンスが一つあります.プロト.属性はプロトタイプオブジェクトを指し、他の実装においてスクリプトは直接このポインタにアクセスしない方法である.
  • 例とプロトタイプオブジェクトとの直接的な関係はないが、プロトタイプオブジェクトのconstructor属性もすべてのインスタンスに共有されるので、各インスタンスはconstructor属性を介して構造関数にアクセスでき、すなわちインスタンスのタイプを判断することができることに留意されたい.
  • 原型オブジェクトに関する方法
  • Person.prototype.isProttypeOf:インスタンスの[prototype]ポインタが構造関数のプロトタイプオブジェクトを指すかどうかを判断する.
  • Object.get ProttypeOf(person 1):インスタンスに戻る[prototype]ポインタの値、すなわち構造関数に対応するプロトタイプオブジェクトです.これはECMAScript 5が提供する方法です.ie 9+
  • person 1.hasOwnProperty():属性がインスタンスに存在するかどうかを判断し、インスタンスのプロトタイプではない.
  • Object.getOwn PropertyDescriptor(person 1、‘name’):着信したname属性がperson 1のプロトタイプの属性である場合、undefinedしか得られないので、Object.getOwn PropertyDescriptor(Person.prototy,name)を使用して、このプロトタイプに直接に呼び出す方法.
  • Object.keys():オブジェクトの列挙可能なインスタンス属性を取得する.
  • Object.getOwn PropertyNames()は、列挙できない例示的な属性を含むオブジェクトのすべてのインスタンス属性を取得する.
  • 原型オブジェクトに関する操作子
  • delete:プロトタイプオブジェクトの属性は、インスタンスにとって、名義上は読み取り可能であり、変更不可である.(実際には、属性の値がベースタイプの値であれば、正しいといえる.属性の値が参照タイプの場合は、プロトタイプの属性値を変更することができ、このような変更はインスタンス属性を追加することはなく、属性指向のアドレスを変更することはできない.ここでは、ES 6に追加されたconstと同じ原理である.)(person 1.name=「s」)プロトタイプオブジェクト上の対応する属性の値を変更することなく、インスタンスに新しいインスタンス属性を作成します.このような操作をすると、この属性の値をnullに設定しても、プロトタイプの属性にはアクセスできません.delete操作子はインスタンス属性を完全に削除するために使用されます.このようにしてプロトタイプの属性に再アクセスできます.
  • in:inオペレータが単独で使用する場合、オブジェクトがある属性を持つかどうかを判断するために使用され、この属性がインスタンス属性であろうと、プロトタイプの属性であろうと、Boolean値を返します.for-inエルゴードオブジェクトのすべてのエニュメレート・属性を使用してもいいです.例が元のタイプでは挙げられない属性を書き換えたら、for-innも遍歴できます.
  • 簡単なプロトタイプの文法を変更します.Person.prototypeを複数回書くことを避けるために、もっと簡単なプロトタイプの文法を採用します.私たちが必要な属性を含む字面量のオブジェクトを直接プロトタイプのオブジェクトに値を付けます.このように操作しても、instance ofで対象のタイプを判断できますが、この時点でプロトタイプのconstruct属性はObjectを指しています.コンストラクタ;私達はconstructorを手動でPersonに設定できますが、同時にconstructorの属性を列挙可能な属性に変更します.この時、construtorを列挙できない属性に設定し直す必要があります.具体的には下記のように実現します.
    function Person () {
           }
    //               
    Person.prototype = {
           
        name: 'nicho',
        sayname: function () {
           
            console.log(this.name)
        }
    }
    //        constructor  
    Object.defineProperty(Person.prototype, 'constructor', {
           
        enumerable: false,
        value: Person
    })
    
    person 1が創建された時、Personのプロトタイプのオブジェクトはまだ変更されていません.この時、person 1のプロトタイプです.ポインタが指す最初のプロトタイプのオブジェクトは、Person.prototypeが指すオブジェクトを変更した後、person 1は新しいプロトタイプのプロトを指していないので、新しいプロトタイプのオブジェクトに定義された属性と方法にアクセスできなくなります.いつでも、インスタンスの[prototype]ポインタがプロトタイプのオブジェクトを指していることを覚えてください.
  • プロトタイプモードの問題プロトタイプパターンは、構造関数への参照および関連属性の初期化のステップを省略し、すべてのインスタンスのデフォルトの属性値が同じになる.もう一つの大きな問題は共有性によって引き起こされる.属性の値が参照タイプである場合、この属性はすべてのインスタンスに反映される.この2つを解決するために.この問題については、構造関数モードとプロトタイプモードを組み合わせることができます.
  • 組み合わせは、このモードでのコンストラクターモードとプロトタイプパターンを使用して、プロトタイプパターン定義方法および他の共有属性を使用して構成関数パターンを定義します.
    function Person () {
           }
    //         
    var person1 = new Person()
    //               ,       ,             
    var proto = {
           
        name: 'nicho',
        sayname: function () {
           
            console.log(this.name)
        }
    }
    Person.prototype = proto
    //        constructor  
    Object.defineProperty(Person.prototype, 'constructor', {
           
        enumerable: false,
        value: Person
    })
    //          
    var person2 = new Person()
    person2.sayname() // nicho
    person1.sayname() // Uncaught TypeError: person1.sayname is not a function