【问题标题】:Javascript : How to add getter to an existing objectJavascript:如何将getter添加到现有对象
【发布时间】:2021-09-24 21:36:14
【问题描述】:

我可以像这样在 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'; }

【问题讨论】:

    标签: javascript


    【解决方案1】:

    试试defineProperty

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

    【讨论】:

    • 我相信上述解决方案的一个问题是,如果您要在 member 对象上使用 Object.assign,则不会像在对象创建期间设置的那样复制 getter 并且不明确的。 jsfiddle.net/ygd20ws4
    • @user1331784 这是因为创建的属性默认是不可枚举的。您可以将描述中的可枚举键设置为 true,Object.assign 将复制 getter。
    • 其实用可枚举键不会复制getter,而是复制时的值。
    【解决方案2】:

    您可以这样使用新的Object.defineProperty

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

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

    【讨论】:

    • 你应该为 FGITW 失败投票。 (实际上你有更多的内容!)
    【解决方案3】:

    这不仅可以通过上述解决方案实现,还可以使用... 运算符。

    // 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)

    ... 是扩展运算符,它“扩展”它所使用的对象的内容,因此得名。例如:

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

    【讨论】:

    • 这实际上是浅拷贝现有对象到一个带有额外 getter 的新对象。更干净的代码。但是如果你不能设置你想要添加 getter 的对象(例如,一个单例/工厂对象)
    【解决方案4】:

    此外,如果不应该从其他值计算旧值,您可以添加自定义 getter 并保留旧值,例如在您的示例中。为此,请使用这样的匿名函数创建额外的上下文层:

    (function(){
        var oldValue = yourObject[targetProperty];
        var currentValue = oldValue;
        var getter = function() {
            return currentValue; // or do something before returning, like applying parseInt or whatever
        };
        var 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
        });
    })();
    

    【讨论】:

      【解决方案5】:

      为了完整性,Reflect.defineProperty 也是一个选项 :)。请注意,Object.definePropertyReflect.defineProperty 的行为不同。

      MDN compares the two functions(以及所有类似的ObjectReflect 方法):

      Method Name Object Reflect
      defineProperty() Object.defineProperty() returns the object that was passed to the function. Returns a TypeError if the property was not successfully defined on the object. Reflect.defineProperty() returns true if the property was defined on the object and false if it was not.

      我更喜欢Reflect,因为我认为布尔检查更有意义,但总的来说,如果您认为可能存在冲突,请记住错误处理(这些在弄乱对象属性时应该很少见,除非您的某个库正在进行类似的、可能相互冲突的更改)。

      【讨论】:

        【解决方案6】:

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

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

        get 表示可以读取属性! set 意味着可以写入属性! 可以看书《JavaScript:The.Definitive.Guide》6版第6章!

        【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-09-06
        • 1970-01-01
        • 2020-07-13
        • 1970-01-01
        • 1970-01-01
        • 2016-04-20
        • 1970-01-01
        • 2010-12-17
        相关资源
        最近更新 更多