1

I'm building a class that is shared between a game engine and an editor. There are some properties and methods I want to be defined in the editor, but not the engine so I wrote the following code

class Asset{
    constructor(){
        this.prop1 = 1;
    }
}

if (window.IS_EDITOR){
    Asset.prototype.editorProp = 2;
}

class Room extends Asset{
    constructor(){
        super();
        this.prop2 = 3;

        console.log(this)
        //expected:   {prop1: 1, prop2: 3, editorProp: 2}
        //what I get: {pro1: 1, prop2: 3}
    }
}

I'm basically just trying to conditionally add another property to the constructor, but I'm confused why the editorProp isn't showing up when I access this.

5
  • 1
    Are you certain window.IS_EDITOR is resolving to true? Commented Jan 1, 2022 at 0:02
  • 2
    Well, editorProp is on the prototype, as you’ve specified. You’re logging the instance instead. Just go through the prototype chain in your console and you’ll find this property. Commented Jan 1, 2022 at 0:03
  • Once you mutate the Asset's prototype, it will stay mutated in both the game engine and editor environment Commented Jan 1, 2022 at 0:17
  • Question about your approach: if you're using class notation, why are you directly accessing the prototype instead of having a static class property setter static setEditorProp(value) { this.editorProp = value; } (where this in static context is the class itself) and a getter get editorProp() { return Asset.editorProp; }? Commented Jan 1, 2022 at 0:25
  • Sorry, I should have clarified: This is a simplified version to illustrate the issue. There are currently about 10 different props and methods that I would like to only be defined in one use case or the other Commented Jan 1, 2022 at 3:33

2 Answers 2

4

I'm confused why the editorProp isn't showing up when I access this.

Because it's on the prototype of your object, just like the .constructor, and won't be printed by default when you console.log it. You'll find it if you expand the prototype, or if you console.log(Object.getPrototypeOf(this)). You still can access it as this.editorProp with the expected value, as it is inherited.

I'm trying to conditionally add another property to the constructor

If you want to add the property to the instance in the constructor, you should actually do it in the constructor:

class Asset {
    constructor() {
        this.prop1 = 1;
        if (window.IS_EDITOR) {
            this.editorProp = 2;
        }
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

That was my original approach, but it seemed redundant to do the check every time an asset was created since IS_EDITOR will never change during runtime and editing the prototype seemed cleaner and more efficient. If it isn't possible though then this will do
Well what do you need the (conditional) editorProp property for in the first place?
And yes, it totally is possible to use the prototype, it works just fine, it's just not visible in console.log.
0

Like pointed out, console.log is just logging the object, not what's in the prototype chain. So doing console.log(this.editorProp) will indeed return 2, as the prototype chain is now been used.

If you want to see the object with the prototype flattened it's pretty easy to do using in. In the example below I've added a simple function called flat that does this.

Also worth noting adding methods to a class will make them automatically none enumerable, but if you add a method to the prototype it will be enumerable. So an example below I've also added a function called fn but using defineProperty to stop it been enumerable.

window.IS_EDITOR = true;

class Asset{
    constructor(){
        this.prop1 = 1;
    }
}

if (window.IS_EDITOR){
    Asset.prototype.editorProp = 2;
    //adding a function this will will be
    //enumerable, so you might want to use
    //defineProperty here.
    Object.defineProperty(
      Asset.prototype,
      'fn',
      {value: () => {console.log('fn called')}, enumerable: false});
}

class Room extends Asset{
    constructor(){
        super();
        this.prop2 = 3;
        console.log(this.flat());
        this.fn();
        //expected:   {prop1: 1, prop2: 3, editorProp: 2}
        //what I get: {pro1: 1, prop2: 3}
    }
    flat() {
      const ret = {};
      for (const i in this) ret[i] = this[i];
      return ret;
    }
}

new Room();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.