Object.defineProperty()個人的な理解

Object.defineProperty()個人的な理解

Object.defineProperty()は、オブジェクトのプロパティのプロパティを定義するために使用されます。これらのプロパティはオブジェクトの内部値に属しているため、JSで直接アクセスすることはできません。

ES5には、次の2つの属性があります。データ属性アクセサのプロパティ

データ属性

データ属性には、データ値値の読み取りと書き込みが可能な位置であるdata属性には、その動作を説明するために使用される4つの特性があります。

  • [[構成可能]]は、属性を削除できるかどうか、属性の特性を変更できるかどうか、属性をアクセサー属性に変更できるかどうかを示します。オブジェクトに直接属性を定義する場合、デフォルト値はtrueです。
  • [[列挙可能]]ループを介して属性を返すことは可能ですか?オブジェクトに直接定義された属性。この属性のデフォルトはtrueです。
  • [[書き込み]]属性の値を変更することは可能ですか。オブジェクトに直接定義された属性。この属性のデフォルト値はtrueです。
  • [[値]]属性のデータ値。属性値を読み取るときはこの場所から読み取り、新しい属性を書き込むときはこの場所に新しい値を保存します。デフォルト値は未定義です

Object.defineProperty()を使用して、プロパティのデフォルトプロパティを変更し、プロパティが配置されているオブジェクト、プロパティ名、記述子オブジェクトの3つのパラメータを受け入れます。記述子オブジェクトのプロパティは上記の4つのプロパティである必要があり、できません。他のプロパティがあります。1つ以上の値を設定すると、対応する特性値を変更することができます

例:

let obj = {
    
    
    name: "lalala",
    age: 15,
    idol: 'CR7'
};
Object.defineProperty(obj , 'name' , {
    
    
    writable: false,    //不可被修改
    enumerable: false,   //不可被遍历
    value: "Well"  
})

console.log(obj.name)    //Well
obj.name = 'Nigo'   //严格模式下会报错,非严格模式没事
console.log(obj.name)  //Well

Object.keys(obj).forEach(key => {
    
    
    console.log(key);   //age , idol   不包含name属性
})

object.defineProperty()メソッドを複数回呼び出して同じプロパティを変更できますが、最初の変更で構成可能オブジェクトがfalseに設定されている場合、再度変更することはできず、エラーが報告されます。

let obj = {
    
    
    name: "lalala",
    age: 15,
    idol: 'CR7'
};
Object.defineProperty(obj , 'name' , {
    
       //没有设置configurable:false是可以再次修改的
    writable: false,    //不可被修改
    enumerable: false,   //不可被遍历
    value: "Well"  
})

console.log(obj.name)    //Well
obj.name = 'Nigo'   //严格模式下会报错,非严格模式没事
console.log(obj.name)  //Well

Object.keys(obj).forEach(key => {
    
    
    console.log(key);   //age , idol   不包含name属性
})



Object.defineProperty(obj , 'name' , {
    
    
    writable: true,    //该为true
    enumerable: false,   //不可被遍历
    value: "Well"  
})

obj.name = 'Nigo'   //可以修改属性了
console.log(obj.name)  //Nigo
let obj = {
    
    
    name: "lalala",
    age: 15,
    idol: 'CR7'
};
Object.defineProperty(obj , 'name' , {
    
       //没有设置configurable:false是可以再次修改的
    configurable:false,   //不可再次修改该属性的特性
    writable: false,    //不可被修改
    enumerable: false,   //不可被遍历
    value: "Well"  
})

console.log(obj.name)    //Well
obj.name = 'Nigo'   //严格模式下会报错,非严格模式没事
console.log(obj.name)  //Well

Object.keys(obj).forEach(key => {
    
    
    console.log(key);   //age , idol   不包含name属性
})



Object.defineProperty(obj , 'name' , {
    
       //这里直接报错
    writable: true,    
    enumerable: false,   
    value: "Well"  
})


アクセサのプロパティ

アクセサプロパティにはデータ値は含まれていませんが、ゲッター関数とセッター関数のペアが含まれています(必須ではありません)。

さらに、プロパティにgetメソッドとsetメソッドがある場合、それはアクセサープロパティです。

ゲッター関数

アクセサプロパティを読み取るときに呼び出される関数

セッター機能

アクセサプロパティを書き込むときに、setter関数を呼び出して新しい値を渡すと、setter関数がデータの処理方法を決定します。

アクセサプロパティは直接定義できません。Object.defineProperty()でも定義する必要があります。

        const obj = {
    
    
            name: 'Well',
            _age: 22,  //表示只有通过对象方法能访问到的属性
        }

       Object.defineProperty(obj , 'age' , {
    
    
           configurable:true,   //表示能否delete删除属性,能否修改属性的特性,能否将属性改为数据属性,默认false
           enumerable: true,  //能否被遍历到,默认false
           get() {
    
    
               console.log("获取age的值");
               return this._age;
           },
           set(newV) {
    
    
               console.log("写入新值");
               this._age = newV;  //可以通过setter函数改变对象中的其他属性值
           }
       });
       obj.age = 24;  //写入新值
       console.log(obj.age); //获取age的值    24
       obj.age = 26;  //写入新值
       console.log(obj.age);  //获取age的值   26
       console.log(obj._age) //26

アクセサの属性名をオブジェクトの元の属性名と同じにすることはできません。同じにしないと、無限ループのためにスタックがオーバーフローします。

監視オブジェクトのデータの変更:

 const obj = {
    
    
            a: 1,
            b: 2,
            c: 3
        }

        Object.keys(obj).forEach(key=>{
    
    
            let value = obj[key]
            Object.defineProperty(obj,key,{
    
    
                get(){
    
    
                    console.log(`获取${
      
      key}的行为被我劫持了`)
                    return value
                },
                set(v){
    
    
                    console.log(`${
      
      key}的改变被我劫持了`);
                    value = v;
                }
            })
        })
        console.log(obj.b);  //获取b的行为被我劫持了  2
        obj.c = 5;  //c的改变被我劫持了  

ゲッターとセッターを同時に定義する必要はありません

セッターを定義するだけで、読み取りはできず、書き込みのみが可能です。ゲッターなしでプロパティを読み取ると、strictモードはエラーを報告し、non-strictモードはundefinedを返します。

ゲッターのみを定義すると、読み取りのみが可能で、書き込みはできず、書き込みを試みることができます。エラーは厳密モードで報告され、非厳密モードでは無視されます。

複数の属性を定義する

Object.defineProperties()、このメソッドは2つのパラメーターを受け取ります。どちらも2つのオブジェクトであり、最初のパラメーターはプロパティを追加および変更するオブジェクトです。

2番目のオブジェクトの属性は、最初のオブジェクトで追加または変更された属性に対応している必要があります

例:

const people = {
    
    
    _name: 'Nigo',
    _age: 28
};

Object.defineProperties(people , {
    
    
    _name: {
    
    
        value: 'HaHa',
        //可修改其他特性
    },
    name: {
    
     //定义一个访问器属性
    	get() {
    
    
    		return this._name;
		}
	},
     age: {
    
    
         set(newV) {
    
    
             this._age = newV
         }
     }
})

属性のプロパティを読む

Object.getOwnPropertyDescriptor()

2つのパラメーターの属性が配置されているオブジェクトと、読み取られる属性の名前。このメソッドの戻り値はオブジェクトです。

データ属性の場合、返されるオブジェクトには、構成可能、列挙可能、書き込み可能、​​値が含まれます

アクセサ属性の場合、返されるオブジェクトには、構成可能、列挙可能、取得、および設定が含まれます

JSでは、任意のオブジェクトでObject.getOwnPropertyDescriptor()メソッドを使用できます

おすすめ

転載: blog.csdn.net/YL971129/article/details/113733956