简体   繁体   English

在定义的属性上使用Object.defineProperty

[英]Using Object.defineProperty on a defined property

Consider a pattern like this, where we want to define a nice getter/setter interface for a property to hide some internal validation: 考虑一下这样的模式,我们想要为属性定义一个不错的getter / setter接口,以隐藏一些内部验证:

var validThings = {
    'pretty name a': 3293293,
    'pretty name b': 8275850,
    'pretty name c': 2983855
};


function Constructor() {
    var internalThing = {
        name: 'pretty name a',
        id: '3293293'
    };

    Object.defineProperty(this, 'thing', {
        get: function() { return internalThing.name; },
        set: function(val) {
            var id = validThings[val];
            if (id) internalThing = { name: val, id: id };
        }
    });
}

This lets us avoid worrying about the ids so we can just set 'thing' like this: 这使我们避免担心ID,因此我们可以像这样设置“东西”:

var constructoid = new Constructor();
constructoid.thing = 'pretty name b';
constructoid.thing; // 'pretty name b';

And of course it prevents us from setting it to an invalid value: 当然,这可以防止我们将其设置为无效值:

constructoid.thing = 'pretty name d';
constructoid.thing; // 'pretty name b';

But let's say we do want to be able to access the ID from outside the object as well. 但是,假设我们确实也希望能够从对象外部访问ID。 The most natural interface for that would be as a property of thing 最自然的接口是事物的属性

constructoid.thing.id

But how would one go about defining such a property when 'thing' is itself a getter/setter? 但是,当“事物”本身就是吸气剂/吸气剂时,如何定义这样的属性呢? I am used to being able to throw properties on anything if needed, in JS -- functions, arrays, ice cream cones, whatever. 我习惯于在JS中根据需要在任何东西上抛出属性-函数,数组,冰淇淋蛋筒等。 But it seems to not be possible in this case, at least not in any way I've been able to think of. 但是在这种情况下似乎是不可能的,至少以我无法想到的任何方式。

Object.defineProperty(this.thing, 'id', {...}) // <-- error

Of course, I can simply define a property on the Constructor object itself, something like 'thingID', or I could return both the name and ID from the thing getter. 当然,我可以简单地在Constructor对象本身上定义一个属性,例如“ thingID”,或者可以从事物获取器返回名称和ID。 I'm not looking for a solution like that, however obvious; 我不是在寻找那样的解决方案,尽管很明显。 this is a hypothetical question about whether it's actually possible to define a property on a defined property. 这是一个关于是否可能在定义的属性上定义属性的假设问题。

I found a way: 我找到了一个方法:

    Object.defineProperty(this, 'thing', {
        get: function() {
            var name = internalThing.name;
            if (!name) return;
            name = new String(name);
            Object.defineProperty(name, 'id', {
                get: function() { return internalThing.id; }
            });
            return name;
        },
        set: function(val) {
            var id = validThings[val];
            if (id) internalThing = { name: val, id: id };
        }
    });

I've never had an occasion to use the String constructor before, but it turns out it allows you to add properties to a specific string. 我以前从未使用过String构造函数,但事实证明,它允许您将属性添加到特定的字符串。 If anyone has a better approach, I'm still curious about other ways to achieve this effect. 如果有人有更好的方法,我仍然对实现此效果的其他方法感到好奇。


Edit: 编辑:

As Felix Kling pointed out, String as a constructor is too much trouble. 正如Felix Kling指出的那样,将String作为构造函数是很麻烦的。 The above pattern would work without caveats if the value returned by the first getter weren't primitive, so it could be useful in some situations, but for primitives I don't think there's any good solution. 如果第一个getter返回的值不是原始值,则上述模式将毫无警告地起作用,因此在某些情况下它可能会有用,但是对于原始值,我认为没有任何好的解决方案。 The object requirement is true for value properties as well -- although unlike accessors, defineProperty will accept a value-type previously defined property as its first argument. 对象要求也适用于值属性-尽管与访问器不同,defineProperty将接受先前定义的值类型属性作为其第一个参数。 Presumably a value property is considered a real object, while an accessor property is a ... phantom abstraction? 假定值属性被视为真实对象,而访问器属性则是...幻像抽象? Whatever it is, you can't pin things to 'it' until 'it' exists (ie, within a get function). 无论是什么,您都无法将其固定到“它”,直到“它”存在(即在get函数中)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM