关于 Object.defineProperty()

通常,定义或者修改一个JS对象,有以下方式:

// 1. 字面量

let obj = {
    name: 'cedric',
    age: 18
}


// 2. new Object()
let obj = new Object()
obj.name = 'cedric'
obj.age = 18


// 3. Object.create()

// 4. 工厂模式

// 5. 构造函数

// 6. ...

上面当对象创建一个属性后,如:obj.name = 'cedric', 其中 name 就是一个 【普通属性】,ta的值允许修改或删除,也可以通过for..inObject,keys 枚举遍历。

如果要更精准的控制对象属性,可以使用 Object.defineProperty() 方法。

语法

Object.defineProperty(obj, prop, descriptor)

// obj: 需要定义属性的当前对象
// prop: 当前需要定义或修改的属性名
// descriptor: 属性描述符 

例如:

let obj = {}; // 创建一个新对象

// 在对象中添加一个属性与数据描述符的示例
Object.defineProperty(obj, "name", {
  value : 'cedric',   // 属性 value 的初始化值 cedric
  writable : true,    // 可修改值内容, 默认值 false
  enumerable : true,  // 可枚举,默认 false
  configurable : true  // 可枚举,默认 false
});

属性描述符 - descriptor

属性 说明 默认值
configurable 该属性为true时才可以被删除 false
enumerable 为true时,可以被for...in或Object.keys枚举 false
value 该属性对应的值 undefined
writable 为true时,value才能被赋值运算符改变 false
get 取值的时候,触发 undefined
set 修改属性的时候,触发 undefined

set 和 get

设置set或者get,就不能在设置value和wriable,否则会报错。

let obj = {
    __age: 18
};

Object.defineProperty(obj, 'age', {
    enumerable: true,
    configurable: true,
    get: function () {
        console.log('get------------age');
        return 'My age is ' + this.__age;
    },
    set: function (newVal) {
        console.log('set------------age', newVal);
        this.__age = newVal;
    }
});

console.log(obj.__age);  // 18,  __age为普通属性
console.log(obj.age);  // My age is 18  , 触发 get() 
obj.age = 22;  // 触发 set()

console.log(obj.__age);  // 22
console.log(obj.age);  // My age is 22, 触发 get() 
obj.__age = 33; // 既不触发 set() , 也不触发 get()

console.log(obj.__age);  // 33
console.log(obj.age);  // My age is 33 , 触发 get() 

👉 注意

1. 默认情况下,使用 Object.defineProperty() 添加的属性值是不可修改的

let obj = {};  
 
Object.defineProperty(obj, "age", {
  value : '18',   
});

console.log(obj.age);   // 18

obj.age = 20;

console.log(obj.age);   // 18

2. configurable 可以看做是所有属性描述符的总开关,一旦设置为 false 后(如果不设置,默认值也是 false),后面所有描述符就都不能被改变了。

如果第一次不设置 configurable,或者设置为 false, 第二次再设置 configurable, 就会报错。

let obj = {};  
 
Object.defineProperty(obj, "age", {
  value : '18',   
  configurable:false
});

Object.defineProperty(obj, "age", {
  value : '18',   
  configurable:true
});

// error: Uncaught TypeError: Cannot redefine property: age

3. 表格里面的几个描述符是不允许同时存在的

描述符壳同时具有的键值:

configurable enumerable value writable get get
数据描述符 Yes Yes Yes Yes No
存取描述符 Yes Yes No No Yes

👉 如果同时设置(value或writable)和(get或set)关键字,将报错。

posted @ 2019-08-26 16:13  Mr.曹  阅读(447)  评论(0编辑  收藏  举报