Javascript 带有getter/setter的Object.defineProperty()默认值

Javascript 带有getter/setter的Object.defineProperty()默认值,javascript,Javascript,我在搞一些“经典”遗产,我遇到了一个问题。我正在使用Object.defineProperty()向我的LivingThing类添加属性。我想要一个默认值,以及一个属性getter/setter 我遇到以下错误: Uncaught TypeError: Invalid property. A property cannot both have accessors and be writable or have a value, #<Object> 未捕获类型错误:无效属性。属性

我在搞一些“经典”遗产,我遇到了一个问题。我正在使用
Object.defineProperty()
向我的
LivingThing
类添加属性。我想要一个默认值,以及一个属性getter/setter

我遇到以下错误:

Uncaught TypeError: Invalid property.  A property cannot both have accessors and be writable or have a value, #<Object>
未捕获类型错误:无效属性。属性不能同时具有访问器和可写或具有值#

为什么会出现此错误?使用
Object.defineProperty()
,为属性设置默认值和getter/setter的最佳方法是什么?

如果需要存储,您的getter/setter对将显示一个计算属性,您可以(并且应该)使用实属性备份该属性:

self._isAlive = true;
Object.defineProperty(self, 'isAlive', {
    get: function(){
        return this._isAlive;
    },
    set: function(newValue){
        this._isAlive = newValue;
    },
    writable: true,
    configurable: true
});

想必,在那里放置一些逻辑来证明setter/getter与常规属性的合理性。setter用于包装属性访问

如果没有setter和getter,您只需将其分配给原型即可定义默认值:

LivingThing.prototype.isAlive = true

var o = new LivingThing()

console.log(o.isAlive) // true
需要明确的是,在LivingThing实例上更改该属性将为该实例创建一个属性,而不是更改其
\uuuuu proto\uuuu
中的值

o.isAlive = false

console.log(new LivingThing().isAlive) // still true

使用函数范围的变量来支持定义的属性,并将该变量的初始值设置为默认值:

function LivingThing(){
    self = this;
    var isAlive = true;

    Object.defineProperty(self, 'isAlive', {
        get: function(){
            return isAlive;
        },
        set: function(newValue){
            isAlive = newValue;
        },
        configurable: true
    });

    self.kill = function(){
        self.isAlive = false;
    };
}

可写
不是必需的,因为您有一个setter。这就是你犯错误的原因。您可以使用value/writable(数据描述符)或get/set(访问器描述符)


因此,当您调用
var l=new LivingThing
时,
l.isAlive==true
并且在调用
l.kill()
后,
l.isAlive==false

取决于。您是在使用setter执行任何特殊操作,还是默认值就是您想要的所有行为?setter只是用来用新值替换旧属性值。我相信这是默认的行为,尽管我不确定。好吧,所以你实际上不需要一个setter和getter;)后续问题:什么样的人需要二传手/接球手?我假设每次访问/写入属性时都会发生这种情况。一种是,如果您有一个内部值,而该值的格式不是使用该对象的某个上下文所期望的格式。另一个是,你可以应用副作用或验证。另一个是真正计算的属性,如“length”,其中只有一个getter。因为您已经知道Object.defineProperty,所以您知道不需要getter/setter来使属性成为只读,这曾经是另一个用例。在本例中,当我们最终只使用功能范围变量时,定义实例化对象的属性的目的是什么?您完全可以使用
this.isAlive
/
self.isAlive
变量。getter/setter的用途是,如果您希望操作从实际存储的值中设置/获取的值。例如,如果您希望
isAlive
像字符串一样工作,但存储为布尔值,则可以使用
get:function(){return isAlive?“是的,我仍然活着!!”:“…”;
。它还可以用于更复杂的操作。它还适用于输入验证/条件(即
if([true,false])。indexOf(newValue)==-1)抛出“值必须为true或false”;
isAlive=Boolean(newValue)
)当您提到“我可以使用
self.isAlive
”时,您不是指在getter范围内,对吗?因为这将导致无限循环/max调用堆栈。您将如何实现
self.isAlive