简体   繁体   中英

Setting enumerable property on object prototype

I'm trying to set enumerable property, with setter, on an object prototype.

function Foo(){}
Object.defineProperty(Foo.prototype, 'tag', {
    enumerable: true, configurable: true,
    set: function(x){ 
        if(typeof(x) == "string") {
            Object.defineProperty(this, 'tag', {value: x});
        }
    }
});
var bar = new Foo();

bar.tag = 7;     console.log(bar.tag); // undefined
bar.tag = "baz"; console.log(bar.tag); // "baz"

console.log(bar); // {}
console.log(bar.propertyIsEnumerable('tag')); // false

Everything work as expected, except the last two line.
I just tested the code in node v0.10.25 . I don't understand why the property tag isn't enumerable.
As a workaround, I'm using Object.defineProperty in the constructor against this instead of Foo.prototype , but I would like to understand why object in javascript can't inherit from enuerable properties.

The problem is that your two Object.defineProperty call define different properties:

  • One setter property on the prototype
  • One value property on each this , ie instance

While the one on the prototype is enumerable and configurable, the instance property will not "inherit" these descriptors; and they will default to false on the new descriptor. You will need to set them explicitly:

Object.defineProperty(Foo.prototype, 'tag', {
     enumerable: true, configurable: true,
     set: function(x){ 
         if (typeof(x) == "string")
             Object.defineProperty(this, 'tag', {
                 enumerable:true, configurable:true, // still non-writable
                 value: x
             });
     }
});

You re assign tag in the set function (shadowing tag by creating the member on the Foo instance named bar) but don't set it to enumarable or configurable try the following:

function Foo(){}
Object.defineProperty(Foo.prototype, 'tag', {
    enumerable: true, configurable: true,
    set: function(x){ 
        if(typeof(x) == "string") {
            Object.defineProperty(this, 'tag', {
              value: x,
              enumerable: true
            });
        }
    }
});
var bar = new Foo();

bar.tag = 7;     console.log(bar.tag); // undefined
bar.tag = "baz"; console.log(bar.tag); // "baz"

console.log(bar); // { tag="baz" }
console.log(bar.propertyIsEnumerable('tag')); // true

More info about shadowing members, constructor functions and prototype: https://stackoverflow.com/a/16063711/1641941

I think you can only define properties for an object, not on a prototype or a constructor function, see also this post .

That why putting the object.defineProperty inside the constructor will work: this inside the constructor is an object.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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