1

I'm trying to put some structure to my JavaScript code and want to add some prototype functions to a namespace, like this:

Person.drink();
Person.eat.steak();

I've tried something like this, but it doesn't work as expected:

var Person = function() {
    this.thirsty = true;
    this.hungry = true;    

    this.drink();
    this.eat.steak();
}

Person.prototype.drink = function() {
    this.thirsty = false;
}

Person.prototype.eat = {
    steak: function() {
        this.hungry = false;
    }
};

var me = new Person();
console.log(me.thirsty, me.hungry);

Console output: false, true (Fiddle: http://jsfiddle.net/upwz4u32/2/)

Why does my nested/namespaced function doesn't have access to it's instance variables?

2
  • 4
    because this in the second context is me.eat jsfiddle.net/upwz4u32/3. try to use call/apply like this: jsfiddle.net/upwz4u32/4 Commented Sep 11, 2015 at 13:55
  • You confuse different concepts. Person is a class, not namespace, Commented Sep 11, 2015 at 14:07

2 Answers 2

1

Instead of

this.eat.steak();

Go with

this.eat.steak.call(this);

As @lordvlad said, in your code this is refering to the eat object of the prototype.

Anyway, defining eat as an object of the prototype defining method itself is weird in my opnion.

Why not go for something like :

Person.prototype = {
    eat: function(meat) {
        switch (meat) {
            case "steak":
                this.hungry = false;
            break;
            // ...
        }
    },
    // drink :   
}
Sign up to request clarification or add additional context in comments.

1 Comment

It's just an example. There are hundreds of lines of code that I don't want do add inside a switch statement :) call does exactly what I want, thank you!
1

Why does my nested/namespaced function doesn't have access to it's instance variables?

Because when you do me.eat.steak(), the this in the call to steak is eat, not me.

You basically cannot do what you're talking about in ES5 and before without using call if you're going to write to properties via this within steak. If you were only going to read them, it would be possible by making eat an object whose prototype is the instance of Person.

In ES6, you could do it by making eat a Proxy object wrapped around the person instance, but at that point it's getting really convoluted.

Instead, either make eat a real object that then writes back to its Person when necessary, or just use a naming convention (me.eat$steak(), for instance).

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.