0

I have this module:

exports.yeah = {
   hallo: {
     shine: "was",
     yum: this.hallo.shine
   }
}

As you can see I try to reference shine in yum: this.hallo.shine

But when I do try to execute my script I get this error:

TypeError: Cannot read property 'shine' of undefined

It seems like that the scope is wrong!

I tried different things for example module.exports.yeah.hallo.shine

But it simply won't work! How can I fix this error? Thanks

John Smith
  • 6,105
  • 16
  • 58
  • 109

2 Answers2

2

When you reference this.hallo, the VM is still creating the object and hasn't assigned it to hallo yet. You need to initialize that field later.

In order to build your example:

exports.yeah = {
   hallo: {
     shine: "was",
     yum: this.hallo.shine
   }
}

the VM will need to create

{
  shine: "was",
  yum: this.hallo.shine
}

and assign it to hallo as it creates

{
   hallo: {
     shine: "was",
     yum: this.hallo.shine
   }
}

which it then assigns to exports.yeah.

This is much like function parameters being evaluated before the function is called.

When you reference this.hallo.shine, that chain has not yet been created. Since you're using object literals, you can't rely on this.shine either, since this points to the scope.

You need to use late(r) initialization, like:

exports.yeah = {
   hallo: {
     shine: "was"
   }
}
exports.yeah.hallo.yum = exports.yeah.hallo.shine;
ssube
  • 47,010
  • 7
  • 103
  • 140
2

You could use javascript getters

var exports = {};
exports.yeah = {
  hallo: {
    shine: "was",
    get yum() {
      return this.shine
    }
  }
};
document.write(exports.yeah.hallo.yum);

Note, this in the context of the getter will refer to hallo and not yeah

According to the documentation

The get syntax binds an object property to a function that will be called when that property is looked up.

So since the getter function is called(looked up) after object initialization, this can be used to reference shine

Update

Lets say the object is build like that {hallo1: {..}, hallo2: {..} } . And now I want to reference in hallo1.yum = hallo2.shine Is that possible?

Yes, it is possible because at the time of getting the object is initialized and you can refer to the object itself rather than this

var exports = {};
exports.yeah = {
  hallo1: {
    shine: "was",
    get yum() {
      return exports.yeah.hallo2.yum;
    }
  },
  hallo2: {
    shine: "is",
    get yum() {
      return this.shine;
    }
  }
};
document.write(exports.yeah.hallo1.yum);
AmmarCSE
  • 30,079
  • 5
  • 45
  • 53
  • Really nice! I didn't know that something like this exists. One Question: Lets say the object is build like that `{hallo1: {..}, hallo2: {..} }` . And now I want to reference in `hallo1.yum = hallo2.shine` Is that possible? Thanks! – John Smith Jun 10 '15 at 19:45
  • If you can use these, do! They're really good and will make life a lot easier. – ssube Jun 10 '15 at 19:50
  • @JohnSmith, sorry I mixed them up to reference `hallo2.yum = hallo1.yum` let me know if you want me to do it exactly how you wanted. But, if you get the picture you should be able to do it the other way. – AmmarCSE Jun 10 '15 at 19:56