0

I am trying to make a Person class with a Person.energy property that contains a Person.energy.value number and a Person.energy.rest function that restores the Person.energy.value.

When I define Person.energy, I can set properties based on the this.ability property. But when I try to update properties in a method, I lose the scope that grants access to this.ability. I've crafted an example to explain what I mean...

In the definition for Person.energy below, the this.ability variable is accessed to set the Person.energy.initial and .value variables. This seems to work fine since I can console.log the variables after the object is created. However, when I try to access the same this.ability variable as part of the Person.energy.rest function, it is undefined. This seems to be a scope issue.

I understand that I am not doing a good job of organizing my class methods and properties but I don't know what the proper way to do it is. What is a good javascript class pattern to define methods of properties that can still access the sibling properties of the parent?

== Code ==

function Person() {
    this.init = function() {
        //later: more complex var assignment
        var talent = 0.5;
        var skill = 0.5;
        return [talent, skill];
    };
    [this.talent, this.skill] = this.init();
    this.calculate();
    return this;
}

Person.prototype.calculate = function() {
    this.ability = this.talent * this.skill;
    this.energy = {
        initial: this.ability * 100,
        value: this.ability * 100
    };
    this.energy.rest = function() {
        console.log(this.ability, " <--- this.ability out of scope");
        var amount = this.ability * Math.random();
        this.value = this.value + amount;
    };
};

p = new Person();
console.log(p.energy.value, " <--  calculated using this.ability");
p.energy.rest();

== Console.log ==

25   <--  calculated using this.ability
undefined  <--- this.ability out of scope
2
  • 2
    Calling something like p.energy.rest() will end up calling the rest() method with this set to p.energy and there is no direct way to make it be p. The likely solution to your problem is to NOT nest methods into an extra object. Methods should be attached to the object that they want the this pointer of. You can put a parent reference into p.energy that points to p if you must and then you can use this.parent to get the p object from p.energy.rest(), but usually the better solution is to just get rid of the nested object. Commented Jan 4, 2016 at 6:17
  • I discovered a workaround. Since p.energy.initial is equal to this.ability * 100, I can use this.initial/100 instead of this.ability within the p.energy.rest function and it works perfectly. However, your explanation of the proper way is highly valued. Thank you. Commented Jan 4, 2016 at 6:30

1 Answer 1

3
Person.prototype.calculate = function() {
    var oPerson = this;//will be referring to person object which will have scope across this function.
    this.ability = this.talent * this.skill;
    this.energy = {
        initial: this.ability * 100,
        value: this.ability * 100
    };
    this.energy.rest = function() {
        console.log(oPerson.ability, " <--- this.ability out of scope");
        var amount = oPerson.ability * Math.random();
        this.value = this.value + amount;
    };
};
Sign up to request clarification or add additional context in comments.

1 Comment

This is a working solution that resolves the scope issue. Moreover, it shows explicitly how to define a scoped variable that is treated as global by the property's method. Thank you. In the long run, I think @jfriend00 is right that it's best to define the methods without nesting them.

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.