Object.defineProperty()个人理解

Object.defineProperty()个人理解

Object.defineProperty()用于定义对象中属性的特性,这些特性属于对象内部值,因此在JS中不能直接访问它们。

在ES5中,有两种属性,包括数据属性访问器属性

数据属性

数据属性包含一个数据值的位置,在这个位置可以读取和写入值,数据属性有4个用于描述其行为的特性

  • [[ Configurable ]] 表示能否delete删除属性,能否修改属性的特性,能否将属性改为访问器属性,直接在对象上定义属性时,默认值为true
  • [[ Enumerable ]] 能否通过循环返回该属性。直接在对象上定义的属性,该特性默认为true
  • [[ Writing ]] 能否修改属性的值。直接在对象上定义的属性,该特性默认值为true
  • [[ Value ]] 该属性的数据值。读取属性值时,从这个位置读,写入新属性时,将新值保存在这个位置。 默认值为undefined

使用Object.defineProperty() 修改属性的默认特性,接受三个参数: 属性所在的对象, 属性名 ,以及一个描述符对象 描述符对象的属性必须是上述四个特性,不能有别的属性。设置其中的一个或多个值,就可以修改对应的特性值

例:

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()方法去修改同一个属性,但是如果第一次修改将configurable设为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"  
})


访问器属性

访问器属性不包含数据值,包含一对儿getter和setter函数(不是必须的)

另外,当一个属性设置了get 和 set 方法,它就是一个访问器属性

getter函数

读取访问器属性时调用的函数

setter函数

写入访问器属性时,调用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的改变被我劫持了  

不是一定要同时定义getter和setter

​ 只定义setter意味着只能写入,不能读,读没有getter的属性时,严格模式报错,非严格模式返回undefined

​ 只定义getter意味着只能读,不能写入,尝试写入,严格模式下报错,非严格模式会忽略

定义多个属性

Object.defineProperties(),该方法接收两个参数, 都是两个对象 , 第一个是要添加和修改属性的对象

第二个对象中的属性要与第一个对象中添加或修改的属性对应

例:

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()

两个参数 属性所在的对象和要读取属性的属性名,该方法返回值是一个对象

如果是数据属性, 返回的对象中包含configurable、 enumerable、 writabele 、 value

如果是访问器属性,返回的对象中包含configurable 、 enumerable、 get 、 set

在JS中,可以对任何对象使用Object.getOwnPropertyDescriptor() 方法

你可能感兴趣的:(javascript)