0

I'm currently studying javascript prototypes and I'm quite confused on how it really works. I have this code snippet and it works perfectly

function Message(msg){
    this.msg =msg;
}

Message.prototype = {

    constructor:Message,
    display: function(){
         return this.msg;
    }

};


alert(new Message("007").display());

What this code is trying to do is to illustrate a simple encapsulation by using javascript.

Now the problem is, I want to add this text:this.msg instead of using the display method

Message.prototype = {

    constructor:Message,
    someValue:99,
    text: this.msg,
    display: function(){
         return this.msg;
    }

};

But i only get undefined when i call

 alert(new Message("007").text);

But calling

alert(new Message("007").someValue);

Displays 99. What is the problem here?

cattarantadoughan
  • 509
  • 1
  • 6
  • 15
  • That is because while preparing `Message.prototype` object, `this` does not refer to the `Message` class. – Prakash Sharma Mar 21 '18 at 05:39
  • If you want some *shared property* on your prototype object access properties (like `.msg`) of individual instances, you need a getter! – Bergi Mar 21 '18 at 05:51
  • @Bergi getter from the original object or in prototype? – cattarantadoughan Mar 21 '18 at 13:54
  • @ReubenJaMesAveñoGruta I mean `get text() { return this.msg }` in the prototype. Accessing `.text` on an instance will have that instance as `this`. – Bergi Mar 21 '18 at 16:16

1 Answers1

2

At the time the prototype is being declared, it sees the line text: this.msg, and assigns its text property to the value of its this's msg property. But the this at that point refers to the global/window object - whose .msg property is undefined.

On the other hand, when display is called, the instantiated object has had its constructor run, so the msg property of the instantiated object has been populated, and display is run with the expected calling context. (where this is the instantiated object) Just keep using the display property.

(Also, you don't define the constructor in the prototype: just leave off the constructor: line entirely in the prototype)

CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • Thanks! "But the 'this' at that point refers to the global/window object - whose .msg property is undefined." Does that mean a constructor or function is necessary in order to shadow the global/window object? – cattarantadoughan Mar 21 '18 at 13:51
  • @Reuben JaMes Aveño Gruta you should never use `this` to refer to the global object - in fact, it's forbidden in strict mode, which is good to use. Generally, if you wanted to access a property that was on the global object, you could just use the property name, such as `foo`, to access `window.foo`. – CertainPerformance Mar 21 '18 at 14:16