前端Javascript中对象的属性描述符

var obj = {
  a: 1
}

// 获取属性描述符
var desc = Object.getOwnPropertyDescriptor('obj','a');
console.log(desc);
desc = {
  value: 1,
  writable: true,
  enumerable: true,
  configurable: true
}

// 设置属性描述符 - 其他属性
Object.defineProperty(obj,'a',{
  get: function () {}, // 读取器getter
  set: function () {}, // 设置器setter
})

  1. 通过Object.getOwnPropertyDescriptor('obj','a')可以获得对象obj下a属性的描述符
  2. Object.defineProperty(obj,'a',{ ...desc })重新定义属性描述符
  3. value为值,writable是否可重写,enumerable是否可遍历,configurable表示属性描述符是否可再修改
  4. Object.freeze冻结对象,使其里面的属性值全部不能修改
  5. Object.seal方法封闭一个对象,阻止添加新属性并将所有现有属性标记为不可配置。当前属性的值只要原来是可写的就可以改变。

完整代码如下:

var aGoods = {
  pic: '.',
  title: '..',
  desc: `...`,
  sellNumber: 1,
  favorRate: 2,
  price: 3,
};

class UIGoods {
  get totalPrice() {
    return this.choose * this.data.price;
  }

  get isChoose() {
    return this.choose > 0;
  }

  constructor(g) {
    g = { ...g };
    Object.freeze(g);
    Object.defineProperty(this, 'data', {
      get: function () {
        return g;
      },
      set: function () {
        throw new Error('data 属性是只读的,不能重新赋值');
      },
      configurable: false,
    });
    var internalChooseValue = 0; // 中间变量,外部无法访问
    Object.defineProperty(this, 'choose', {
      configurable: false,
      get: function () {
        return internalChooseValue;
      },
      set: function (val) {
        if (typeof val !== 'number') {
          throw new Error('choose属性必须是数字');
        }
        var temp = parseInt(val);
        if (temp !== val) {
          throw new Error('choose属性必须是整数');
        }
        if (val < 0) {
          throw new Error('choose属性必须大于等于 0');
        }
        internalChooseValue = val;
      },
    });
    this.a = 1;
    Object.seal(this); // 不让加新属性,原属性configurable设置为false,若原有属性可写则可修改
  }
}

Object.freeze(UIGoods.prototype); // 不允许修改原型对象

var g = new UIGoods(aGoods);
UIGoods.prototype.haha = 'abc';
// g.data.price = 100;

console.log(g.haha);

posted @ 2023-03-10 11:00  脆皮鸡  阅读(27)  评论(0)    收藏  举报