Pregunta

I think I'm misunderstanding something here. I have an object that contains a property that I wish to be non enumerable. I want to be able to assign values to it from within the object's functions itself, but when I do so, the property becomes enumerable.

Example:

function ObjectNode() {
}

Object.defineProperty(ObjectNode.prototype, "parent", {
    value:null
    // enumerable and configurable default to false
}

// Pass an ObjectNode instance and set this object node as its parent
ObjectNode.prototype.addChild = function(node) {
    node.parent = this;    // <-- node.parent is now enumerable
    ...more code...
};

What actually happens is that assigning node.parent a value creates a new "own" property called parent, which overrides the original.

Is there a way I can internally assign a value to a non enumerable property without doing this? Or do I have to resort to getter/setter properties that reference a variable within a closure?

EDIT:

GGG deserves credit for answering this, because it was his advice that led me to my ultimate answer.

What I wanted to do was essentially hide a simple property from the 'for(key in object)' statement. I was able to do this as so:

function ObjectNode() {
    Object.defineProperty(this, "parent", {
        value:null, 
        writable:true
    });
}

One reason I balked at this to start with was the mistaken understanding that I did not want the property to be recreated with each instance. But, duh, that's what an instance property is!!!

Thanks, GGG, for helping me realign my brain!

¿Fue útil?

Solución

You have created a property of the prototype property which is non-configurable, but it can still be shadowed by properties of objects created by the constructor.

function ObjectNode() {
}

Object.defineProperty(ObjectNode.prototype, "parent", {
    value: null,
    configurable: false
})

ObjectNode.prototype.addChild = function (node) {
    node.parent = this;    // <-- node.parent is now enumerable
}

var mom = new ObjectNode();
var kid = new ObjectNode();

mom.addChild(kid);

console.log(kid.parent == mom);  // works, logs true

kid.parent = "foo";

console.log(kid.parent);  // works, logs "foo"

ObjectNode.prototype.parent = "foo"; 

console.log(ObjectNode.prototype.parent); // fails, logs null

The thing to remember is that properties of an object are properties of that object only, not properties of other objects with that object in their prototype chain. Instead, try creating a non-configurable property of the new object in the constructor:

function ObjectNode() {
    Object.defineProperty(this, "parent", {
        value: null,
        configurable: false
    })
}

Of course, this will prevent your addChild function from working, since the property is no longer configurable. You could consider defining the property in that function instead, but it will still be configurable until it is set with addChild.

All in all, your best bet in general is to not worry about making things unconfigurable if it's not absolutely critical (and I'm not sure of any case where it would be). The world has gotten along pretty well without that functionality for a long time. ;)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top