BMac
BMac

Reputation: 473

Object.defineProperty does nothing in constructor

I've recently restructured my three.js project and I started to encounter a problem where every object seems to be rendered with the exact same geometry and material. I tracked the problem to this constructor in the debugger:

function Geometry() {
    Object.defineProperty( this, 'id', { value: GeometryIdCount() } );
    this.uuid = exports.Math.generateUUID();
    ...

Chrome shows no properties on the this object after the Object.defineProperty, and id comes back as undefined when things try to use it later. However, when I debug older projects I've made using three.js, the id is defined on this in the debugger after the call.

What could cause Object.defineProperty to do nothing? The most likely culprit is that I've switched from using node.js require calls from Javascript to include three to ES6 import calls from Typescript with a TS compiler, but it's not clear to me why that would have this effect on this constructor.

Upvotes: 0

Views: 473

Answers (1)

Kent Weigel
Kent Weigel

Reputation: 1178

Just saying that "id comes back as undefined" doesn't necessarily mean that Object.defineProperty did nothing, although I do understand that you looked at the properties of this directly after the Object.defineProperty call, and I can't explain that. If GeometryIdCount() returns undefined, then that would explain why the value is undefined later. Have you verified that the property itself is undefined, rather than the property value, after the constructor completes?

It may be like using the word "utilize" instead of "use", or maybe Typescript, ES6 or three.js require it, but why don't you instead write:

this.id = GeometryIdCount();

This will still assign unknown to this.id if the function returns undefined, however.

Update: Your question got me to research exactly what Object.defineProperty does, and it was surprising and very informative. When I worked with WebGL, I didn't use three.js, so I incorrectly assumed that Geometry was a function that you wrote.

When you call Object.defineProperty in the way that you describe, (setting the 3rd argument to an Object with only the "value" property) it sets the writable, configurable and enumerable properties, which all Object properties have, to false. The statement this.id = GeometryIdCount(), on the other hand, will set those 3 properties to true. The author of three.js apparently wanted to assign a unique key to each Geometry object and make it so the user can't change its value. I didn't look for other reasons.

I recommend that you make a copy of your project and whittle out anything that you want to keep secret, (if you want to post it here) and get rid of as much distracting code as you can, to make it easier to determine what is causing the problem. You know, stop removing code when you can no longer reproduce this bad behavior where the id property is not created or it is undefined. I made a small program and tried to guess how to repro the problem, doing bad things like Geometry.prototype.id = undefined before calling var g = Geometry(...), (without the new keyword) but was unable to reproduce the problem. I didn't go so far as to try to override the behavior of GeometryIdCount, or prevent the creation of the id property. That seems like intentional sabotage, and I doubt you suspect that in your case.

Upvotes: 1

Related Questions