Object.defineProperty

1. Object.defineProperty

Object.defineProperty()方法会直接在一个对象上定义个新属性,或者修改一个对象的现有属性,并返回此对象。该方法允许精确地添加或修改对象的属性。

Object.defineProperty(obj, prop, descriptor)

obj:即为作用的对象

prop:即为对象上的某个属性

descriptor:属性描述符,是个对象

// 举例
let obj = {
    name: 'fct'
}
// 为 obj 对象增加属性 age,并设置具体约束
Object.defineProperty(obj, 'age', {
    // ....
})

1.1 属性描述符

属性描述符有两种主要形式:数据描述符存取描述符

数据描述符是一个具有值的属性,该值可以是可写的,也可以是不可写的。

存取描述符是由 getter 函数和 setter 函数所描述的属性。

一个描述符只能是这两者其中之一;不能同时是两者。

// 不能同时是两者。只能以下
Object.defineProperty(obj, 'age', {
    enumerable: false,
    configurable: false,
    
    writable: false,
    value: null
})
// 或
Object.defineProperty(obj, 'age', {
    enumerable: false,
    configurable: false,
    
	get() { return bValue; },
  	set(newValue) { bValue = newValue; }
})

1.1.1 共享可选键值

  • configurable

    默认为 false。当且仅当该属性的 configurable 键值为 true 时,该属性的描述符才能够被改变,同时该属性也能从对应的对象上被删除。

  • enumerable

    默认为 false。当且仅当该属性的 enumerable 键值为 true 时,该属性才会出现在对象的枚举属性中。

1.1.1 数据描述符

  • value

    默认为 undefined。该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。

  • writable

    默认为 false当且仅当该属性的 writable 键值为 true 时,属性的值,也就是上面的 value,才能被赋值运算符改变。

代码展示:

let obj = {
  // 字面量形式,属性描述符值均为 true
  name: 'fct'
};

// 为 obj 对象增加属性 age,并设置具体约束
Object.defineProperty(obj, 'age', {
  // 设置 age 属性值
  value: 18,
  // 使 age属性可以被删除,也可以被重新配置属性描述符
  configurable: true,
  // 使 age 能够被枚举
  enumerable: true,
  // 使 age 能够修改属性值
  writable: true
});

console.log(obj); // { name: 'fct', age: 18 }
obj.age = 21;
console.log(obj.age); // 21

Object.defineProperty(obj, 'age', {
  // 设置 age 属性值
  value: 20,
  configurable: false,
  // 不设置其他属性,均默认 false
  // enumerable: false,
  // writable: false
});

1.1.2 存取描述符

get

属性的 getter 函数,如果没有 getter,则为 undefined。当访问该属性时,会调用此函数。执行时不传入任何参数,但是会传入 this 对象(由于继承关系,这里的this并不一定是定义该属性的对象)。该函数的返回值会被用作属性的值。
默认为 undefined

set

属性的 setter 函数,如果没有 setter,则为 undefined。当属性值被修改时,会调用此函数。该方法接受一个参数(也就是被赋予的新值),会传入赋值时的 this 对象。
默认为 undefined

代码案例展示:

let obj = {
  name: 'fct',
  _address: '成都市'	
};
// 私有属性,不暴露
Object.defineProperty(obj, '_address', {
  enumerable: false,
  configurable: false
});
// 设置暴露属性 address 映射 私有属性 _address
Object.defineProperty(obj, 'address', {
  enumerable: true,
  configurable: true,
  set(value) {
    this._address = value;
  },
  get() {
    return this._address;
  }
});

console.log(obj); // { name: 'fct', address: [Getter/Setter] }
console.log(obj.address); // 成都市
obj.address = '北京市';
console.log(obj.address); // 北京市

// 还可以监听当前属性被获取了几次,被设置了几次值
Object.defineProperty(obj, 'name', {
  enumerable: true,
  configurable: true,
  set(value) {
    console.log("name被赋值");
  },
  get() {
    console.log("name被获取");
    return "name被获取";
  }
});
obj.name = 'xxx'; // 输出 name被赋值
const name = obj.name; // 输出 name被获取

2. Object.defineProperties

Object.defineProperties() 方法直接在一个对象上定义新的属性或修改现有属性,并返回该对象。

Object.defineProperties(obj, props)

obj

定义或修改属性的对象。

props

要定义其可枚举属性或修改的属性描述符的对象。对象中存在的属性描述符主要有两种:数据描述符和访问器描述符。

// 举例
let obj = {
  _age: 18,
  // set age(value) {
  //   this._age = value;
  // },
  // get age() {
  //   return this._age;
  // }
};

Object.defineProperties(obj, {
  name: {
    enumerable: true,
    configurable: true,
    writable: true,
    value: "fct"
  },
  age: {
    enumerable: false,
    configurable: false,
    set(value) {
      this._age = value;
    },
    get() {
      return this._age;
    }
  }
});

console.log(obj.name);  // fct
console.log(obj.age); // 18
obj.age = 21;
console.log(obj.age); // 21
posted @ 2021-12-16 17:00  青柠i  阅读(45)  评论(0编辑  收藏  举报