属性属性(Property Attribute)


Property Attribute


内部スロット/内部メソッド


内部スロットおよび内部メソッドは、ECMAScript仕様で使用されるプライベート・プログラムおよびプライベート・メソッドです.内部スロットと内部メソッドは、ECMAScriptで使用される二重かっこ([Value])です.
原則として、JavaScriptエンジンの内部ロジックであり、開発者が直接アクセスしたり呼び出したりする方法は提供されません.ただし、内部スロットやメソッドの一部に限定され、間接的なアクセス手段が提供される.
たとえば、すべてのオブジェクトに[Prototype]という内部スロット、すなわちobjectがあります.protoで間接アクセスできます.

Property ReportとDisk Lipter


JAvascriptエンジンは、property生成時の状態を表すpropertyツリーを自動的にデフォルト値として定義します.Property Treviewは、JavaScriptエンジンが管理する内部状態値の内部スロットです.property状態は大きく次のように表現できます.

  • [Value]-propertyキーを使用してアクセスされる値をよく知っています.コンフィギュレーションキーで値を変更すると、[Value]に値が再割り当てされ、コンフィギュレーションがない場合は、動的作成後に作成されたコンフィギュレーションの[Value]に値が格納されます.

  • [Writable]-Property値が変更可能であり、ブール値があるかどうかを示します.falseの場合、[Value]は変更できません.(読み取り専用プログラムとなります.)

  • [Entummerable]-Propertyがブール値でリスト可能かどうかを示します.Enumerable値がfalseの場合in文またはObject.keys()などでリストできません.

  • [設定可能]-再定義可能でブール値があるかどうかを示します.falseの場合、propertyの削除、変更は禁止されます.ただし、[Writable]がtrueの場合、[Value]の変更と[Writable]のfalseへの変更は許可されます.
  • JavaScriptエンジンが管理する内部状態値を内部スロットと呼び、その上に[Value]、[Writable]、[Enumerable]、および[Configurable]があります.開発者は直接アクセスできませんが、Objectです.getownPropertyDescriptorメソッドを使用して間接的に確認できます.
    const ironMan = {
     name: 'IronMan' 
    };
    
    console.log(Object.getOwnPropertyDescriptor(ironMan, 'name'));
    // {value: "IronMan", writable: true, enumerable: true, configurable: true}
    // 위 객체를 프로퍼티 디스크립터 객체라고 한다. 프로퍼티 어트리뷰트의 정보를 제공한다. 존재하지 않는 프로퍼티나 상속받은 프로퍼티에 대한 디스크립터를 요구하면 undefined가 반환된다.
    
    // ES8에서 도입된 Object.getOwnPropertyDescriptors 메서드는 모든 프로퍼티의 프로퍼티 어트리뷰트 정보를 제공하는 프로퍼티 디스크립터 객체들을 반환한다.
    const hulk = {
     name: "Hulk"
    }
    
    hulk.power = 20000;
    
    console.log(Object.getOwnPropertyDescriptors(hulk));
    /*
    {
    	name: {value: "Hull", writable: true, enumerable: true, configurable: true}
        power: {value: 20000, writable: true, enumerable: true, configurable: true}
    }
    */

    データ・リソースとビジター・リソース


    Propertyは、大きく分けてデータPropertyとビジターPropertyに分けられます.
  • データproperty-キーと値からなる一般的なpropertyであり、これまで見られたpropertyは実際にはデータpropertyである.
  • ビジター・プロパティ-独自の値を持たずに他のデータ・プロパティの値を読み取りまたは格納するときに呼び出されるビジター関数からなるプロパティ.
  • 私たちは上でデータpropertyを見て、今回は訪問者propertyを見に来ました.ビジター・プロパティには、次のプロパティ・ツリーがあります.

  • [Get]-アクセス者プログラムによってデータプログラムの値が読み込まれたときに呼び出されるアクセス者関数.アクセス者propertyキーを使用してproperty値にアクセスすると、propertyツリー[Get]の値(getter関数呼び出し値)がproperty値に戻ります.

  • [Set]-アクセスプロバイダによってデータプロバイダ値が格納されたときに呼び出されるアクセス者関数.アクセス者プロファイルキーを使用してプロファイル値を保存すると、プロファイルツリー[Set]の値、setter関数が呼び出され、結果がプロファイル値として保存されます.

  • [[Enablerable]-データプロパティと同じです.

  • [[Configurable]-トラフィックプロパティと同様
  • アクセス者関数はgetter/setter関数とも呼ばれます.
    const ironMan = {
     name: "IronMan",
     model: "Mark5",
      
     // getter 함수 (접근자 프로퍼티)
     get fullName() {
       return `${this.name} ${this.model}`; 
     },
      
     set fullName(name) {
       [this.name, this.model] = name.split(' ');
     }
    };
    
    console.log(ironMan.fullName); // IronMan Mark5
    ironMan.fullName = "TonyStark Mark10";
    console.log(ironMan);
    //{name: TonyStart, model: Mark10}
    
    descriptor = Object.getOwnPropertyDescriptor(ironMan, 'fullName');
    console.log(descriptor);
    // {get: f, set: f, enumerable: true, configurable: true}
    これまで、専門的なコメントを知りました.Property Treviewを明確に定義することもできます.
    Object.defineProperty()関数を検索します.(難しくない、直感的)

    オブジェクトの変更を防止


    オブジェクトは変更可能な値で、再割り当てせずに直接変更できます.JavaScriptでは、オブジェクトの変更を防ぐためのさまざまな方法が用意されています.

    Object.preventExtensionsメソッドは拡張オブジェクトを禁止します.つまり、オブジェクトの追加を禁止するプロパティです.
    const ironMan = { name: "tony" };
    
    Object.preventExtensions(ironMan);
    console.log(Object.isExtensible(ironMan)); // false
    
    ironMan.power = 2000; // 무시된다. strict 모드에선 에러가 난다.
    console.log(ironMan); // { name: "tony" }
    
    Object.sealメソッドはオブジェクトを密封します.シールされたオブジェクトは読み書きのみです.
    const ironMan = { name: "tony" };
    
    Object.seal(ironMan);
    console.log(Object.isSealed(ironMan)); // true
    
    // 밀봉된 객체는 configurable이 false다.
    console.log(Object.getOwnPropertyDescriptors(ironMan));
    /*
    {
      name: {value: "tony", writable: true, enumerable: true, configurable: false},
    }
    */
    
    // 프로퍼티 추가 금지
    ironMan.power = 2000; //무시. strict 모드에선 에러
    console.log(ironMan); // {name: "tony"}
    
    // 프로퍼티 삭제 금지
    delete ironMan.name; //무시. strict 모드에선 에러
    console.log(ironMan); // {name: "tony"}
    
    ironMan.name = "stark";
    console.log(ironMan); // {name: "stark"}
    Object.freezeメソッドはオブジェクトをフリーズします.フリーズされたオブジェクトは読み取り専用です.
    const ironMan = { name: "tony" };
    
    Object.freeze(ironMan);
    
    console.log(Object.isFrozen(ironMan)); // true
    
    // 동결된 객체는 writable과 configurable이 false이다.
    console.log(Object.getOwnPropertyDescriptors(ironMan));
    /*
    {
      name: {value: "tony", writable: false, enumerable: true, configurable: false},
    }
    */
    
    // 프로퍼티 추가 금지
    ironMan.power = 2000; //무시. strict 모드에선 에러
    console.log(ironMan); // {name: "tony"}
    
    // 프로퍼티 삭제 금지
    delete ironMan.name; //무시. strict 모드에선 에러
    console.log(ironMan); // {name: "tony"}
    
    // 프로퍼티 값 갱신 금지
    ironMan.name = "stark";//무시. strict 모드에선 에러
    console.log(ironMan); // {name: "tony"}

    不変オブジェクト


    これまで,我々が見た変更防止の方法はいずれも浅い変更であり,直属プログラムのみが変更を防止でき,重複オブジェクトに影響を及ぼさない.したがって、ネストされたオブジェクトにフリーズして不変のオブジェクトを実装するには、すべてのプロパティを再帰する必要があります.freeze()を呼び出さなければなりません.
    function deepFreeze(target) {
      if (target && typeof target == 'object' && !Object.isFrozen(target)){
        Object.freeze(target);
        // 모든 프로퍼티를 순회하며 재귀적으로 동결
        Object.keys(target).forEach(key => deepFreeze(target[key]));
      }
      
      
     return target; 
    }
  • モダンjavascript Deep Dive,李雄模,Wekibooks