javascript 如何将getter添加到现有对象

i5desfxk  于 2023-04-04  发布在  Java
关注(0)|答案(7)|浏览(165)

我可以在JavaScript对象中有一个getter,像这样:

var member = {
    firstName:"XYZ", 
    lastName:"zzz", 
    get fullName(){ return (this.firstName + ' ' + this.lastName); }
}

我甚至可以在运行中添加更多属性,如下所示:

member.isGuest = true;

但是,有没有什么方法可以将getter添加到现有对象中呢?类似这样:

member.isGuest = get isGuest(){ return this.firstName == 'Guest'; }
ltskdhd1

ltskdhd11#

尝试defineProperty

Object.defineProperty(member, 'isGuest', {
  get: function() { return this.firstName=='Guest' }
});
w8f9ii69

w8f9ii692#

您可以通过以下方式使用新的Object.defineProperty

Object.defineProperty(
    member, 
    'prop', 
    {
        get: function() { 
            return this.lastName.toUpperCase()
        }
    }
);

在过去,你必须使用__defineGetter__,但现在它已被弃用。

8qgya5xd

8qgya5xd3#

这不仅可以使用上述解决方案,而且可以使用...运算符。

// Initialize x
var x = {
  x: 5
}

// Log x.x and x.y
console.log(x.x, x.y /* undefined */)

x = {
  ...x, // {...x} is the same as {x: x.x}
  
  // The getter
  get y() {
    return this.x
  }
}

// Log x.x and x.y
console.log(x.x, x.y /* Not undefined */)

// Set x.x to 1234
x.x = 1234

// Log x.x and x.y
console.log(x.x, x.y)

...是spread操作符,它“扩展”对象的内容,因此得名。例如:

  • doSomething(...[1, 2, 3])doSomething(1, 2, 3)相同
  • { ...{x: 1, y: 2, z: 3} }{ x: 1, y: 2, z: 3 }相同
acruukt9

acruukt94#

此外,你可以添加一个自定义的getter,并保留旧的值,如果它不应该是从其他值计算出来的,就像你的例子一样。要做到这一点,使用一个匿名函数创建额外的上下文层,如下所示:

(function() {
    const oldValue = yourObject[targetProperty];
    let currentValue = oldValue;

    const getter = function() {
        return currentValue; // or do something before returning, like applying parseInt or whatever
    };
    const setter = function(newValue) {
        currentValue = newValue; // or add some customization as well
    };

    Object.defineProperty(yourObject, targetProperty, {
        get: getter,
        set: setter,
        enumerable: true, // depending on your needs
        configurable: true // depending on your needs
    });
})();
zzwlnbp8

zzwlnbp85#

为了保证完整性,Reflect.defineProperty也是一个选项:)。注意Object.definePropertyReflect.defineProperty的行为不同。
MDN compares the two functions(以及所有类似的ObjectReflect方法):
| 方法名称|Object|Reflect|
| --------------|--------------|--------------|
| defineProperty()|Object.defineProperty()返回传递给函数的对象。如果属性没有在对象上成功定义,则返回TypeError。|Reflect.defineProperty()返回true,如果属性在对象上定义,则返回false。|
我更喜欢Reflect,因为我认为布尔检查更有意义,但一般来说,如果你认为可能存在冲突,请记住错误处理 *(在处理对象属性时,这些应该是罕见的,除非你的一个库正在进行类似的,可能是冲突的更改)。

osh3o9ms

osh3o9ms6#

Object.defineProperty(obj, prop, descriptor)

这是最好的解决方案,就像上面说的那样。
我想补充的是,为了将getter/setter从对象复制到其他对象,你可以像这样使用Object.create()Object.getOwnPropertyDescriptors

let obj = {
 _value: 0,
}
Object.defineProperty(obj, 'value', {
  configurable: true,
  enumerable: true,
  get() {
    return this._value;
  },
  set(val) {
    this._value = val;
  }
})
const ObjCopy = Object.create(Object.getPrototypeOf(obj),
 Object.getOwnPropertyDescriptors(obj));

这样,您将复制其properties +其getters/setters +其prototype

72qzrwbm

72qzrwbm7#

你只能在一个类中使用get和set,这意味着getter和setter方法。但你可以在类中添加一个函数:

member.isGuest = function isGuest(){ return this.firstName=='Guest';}

member.isGuest()

get表示属性可以被读取!set表示属性可以被写入!你可以在《JavaScript:The.Definitive.Guide》第6版第6章中找到!

相关问题