Home > Enterprise >  Cannot access property added via prototype using "this," in Javascript
Cannot access property added via prototype using "this," in Javascript

Time:01-02

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.

CodePudding user response:

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;
        }
    }
}

CodePudding user response:

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();

  • Related