1

I tried experimenting with private variables and prototypes that didn't use IIFE (which makes objects global so no unique instances).

I tried the following and I'm confused by what I see. I can see it perfectly in the inspector that it's defined but it tells me it's actually not undefined.

What exactly is going on that makes it undefined despite seeing it defined in the inspector?

Screenshot

var Factory = Factory || {};

Factory.Person = function (aname)
{
    var name = 'default';
    function Person()
    {
        name = aname;
    }

    Person.prototype.getName = function() {
        return name;
    }

    return Person;
};

var P = new Factory.Person('test');

alert(P.getName()); //Undefined
Tek
  • 2,888
  • 5
  • 45
  • 73
  • From your picture, you can see in the inspector that `P.prototype.getName` is defined, not that `P.getName` is defined. – apsillers Aug 13 '14 at 15:08
  • Actually, the whole setup is strange, given that the prototype method doesn't even refer to the instance but to the local variable `name`. Think about it like this: Every time you invoke `Factory.Person`, you are creating a new `Person` "class" with (presumably) only one instance. So, instead of having *one* "class" with *n* instances, you'd have *n* classes with *one* instance. – Felix Kling Aug 13 '14 at 15:13
  • Maybe the following can help you in figuring out how prototype is used. http://stackoverflow.com/questions/16063394/prototypical-inheritance-writing-up/16063711#16063711 – HMR Aug 14 '14 at 02:22

1 Answers1

3

getName is a property of the prototype of the Person function. It doesn't exist directly on Person, only on instances of Person (created with the new keyword).

(Note that Person and Factory.Person are very different objects).

Since you are using the factory pattern: Don't touch prototypes or the new keyword.

var Factory = Factory || {};

Factory.Person = function (aname)
{
    // You need to check for aname here
    var name = aname || 'default';

    // There doesn't seem to be any point in making Person a function
    var Person = {};

    // No prototype here
    Person.getName = function() {
        return name;
    }

    return Person;
};

// No new keyword here
var P = Factory.Person('test');

alert(P.getName());

If you wanted to use prototypes, then you would do it like this:

function Person(aname) {
    this.name = aname || 'default';
};

Person.prototype.getName = function() {
    return this.name;
}

var p = new Person('test');

alert(p.getName());
Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
  • Note that in your first example, `getName()` will always return `"default"`, because `P` (`Person`) (which sets `name`) is never executed. – Felix Kling Aug 13 '14 at 15:17
  • Isn't getName also a prototype of the `Person` function on the latter example as well? I don't understand why it works in the global scope and not inside a closure. – Tek Aug 13 '14 at 15:28
  • @Tek — The point of the latter example is that it is rewritten to use prototypes. The reason it works on my prototype example and not yours is that mine uses the `new` keyword on *Person* (which has been given a prototype) and not *Factory.Person* (which hasn't). – Quentin Aug 13 '14 at 15:31
  • @Tek: In your original code, when you call `Factory.Person(...)`, you get back the **function** `Person`, not an instance of `Person`. You'd have to call `var instance = new P(); console.log(instance.getName())` for your code to work. That's the difference between the "global" and the "closure" solution. You are calling two different functions in both cases. – Felix Kling Aug 13 '14 at 15:32
  • @FelixKling I think that deserves it's own answer :) – Tek Aug 13 '14 at 15:37
  • @Tek: I already wrote an answer and deleted it. While I can explain why the code doesn't work, providing a proper solution would require more information from your side (e.g. what exactly you are trying to achieve with this setup, etc). And I just don't have so much time right now ;) – Felix Kling Aug 13 '14 at 15:39
  • @FelixKling In the time that it took you to explain why you couldn't answer... you could have answered. ;) hahaha – Tek Aug 13 '14 at 15:41