Object.defineProperty只能修改setter吗?

时间:2015-07-22 14:41:12

标签: javascript

我希望我的对象有一个字段,当读取时返回字段值,当val写入字段时,我想在写入之前修改val。我目前的代码是:

function Cat(lives) {
    var self = this;

    var privateLives;
    Object.defineProperty(self, 'publicLives', {
        get: function() {return privateLives;},
        set: function(val) {privateLives = 7 * val;}
    });
}

有没有办法在不创建私有变量的情况下执行此操作?理想情况下,我只需要设置这个:

function(val) {self.publicLives = 7 * val;}

但是当setter调用自身时会导致溢出。是否有某种方法可以使它只是不循环setter(所以只有在setter的范围之外的赋值调用setter并且setter中的赋值才能正常分配)?如果可行的话,我不需要在setter写入公共字段时明确定义getter。

2 个答案:

答案 0 :(得分:1)

在ES6中,替代方案是使用带有Proxy object[[Set]] trap

function Cat(lives) {
  return new Proxy(this, {
    set: function(target, prop, val) {
      target[prop] = val;
      if (prop === 'publicLives') target[prop] *= 7;
      return true;
    }
  });
}

答案 1 :(得分:0)

不,这是不可能的 - 属性只能是数据属性或访问者属性,而不是两者。当然,您不一定需要将值存储在setter的私有变量中,您也可以在不同的对象上使用不同的属性或属性(例如在@Oriol的代理中)。如果你想避免私人变量,"私人"属性是标准方法:

function Cat(lives) {
    this.publicLives = lives;
}
Object.defineProperty(Cat.prototype, 'publicLives', {
    get: function() {return this._privateLives;},
    set: function(val) { this._privateLives = 7 * val;}
});

但你也可以做一些棘手的事情并隐藏"私有变量"通过使用重复重新定义的常量getter函数:

Object.defineProperty(Cat.prototype, 'publicLives', {
    set: function setter(val) {
        val *= 7;
        Object.defineProperty(this, 'publicLives', {
            get: function() { return val; }
            set: setter,
            configurable: true
        });
    }
});