1
    /* Game */
    function Game() {
        return {
            items: []
        }
    }

    /* Item */
    function Item(id, name, description, image, price) {
        return {
            getId: function () {
                return id;
            }
        }
    }

    Item.prototype.toString = function() {
        return id + ":" + name;
    };

    /* Logic.. */
    var game = new Game();
    var sword = new Item(1, "Sword", "An iron sword", "sword.png", 10);
    game.items.push(sword);


    console.log(game.items[0] instanceof Item); // false
    console.log(typeof game.items[0]);          // object
    console.log(game.items[0]);                 // Object{}

I have a feeling that because my custom objects go into an array that they lose their 'custom type', in this case Item, when I pull them out. How can I keep a list of Item and have Javascript find out its real type?

1
  • 1
    Array is a red herring. You are retuning object from constructor. That has some interesting behavior (bennadel.com/blog/…), but generally if your constructor function returns object, it is used. If it returns primitive, reference to newly constructed object is used. See specification ecma262-5.com/ELS5_HTML.htm#Section_13.2.2 , point 9 and 10 Commented Sep 24, 2015 at 8:19

1 Answer 1

4

Your constructor functions return plain objects. Constructor functions can do this, but IMO shouldn't do this.

You can change your constructor like this:

/* Game */
function Game() {
    this.items = [];
}

/* Item */
function Item(id, name, description, image, price) {
    this.id = id;
}

// this is very uncommon in JavaScript, looks more like Java
Item.prototype.getId = function () {
    return this.id;
};

Item.prototype.toString = function() {
    return this.id + ":" + this.name;
};

Now it should work like you expect.

Not directly related to this problem, just a hint (because I remarked that defining getId is very uncommon in JavaScript);

In modern JavaScript you don't have to define explicit get/set functions. Instead you typically access the property directly (like a public member in Java). In case you have to apply some logic when the property is accessed (read/write), you can define a function which will be called transparently (see Object.defineProperty):

Object.defineProperty(Item.prototype, 'id', {
    get: function () {
        return this.id;
    },
    set: function (value) {
        if (!isNaN(value)) { // just an example to add some logic
            throw Error('Item.id must be a number!');
        }
        this.id = value;
    }
});
Sign up to request clarification or add additional context in comments.

2 Comments

I see. But the inner return object gives you the ability for private properties. It appears I need to revise my idea. As far as the getId, I wanted a function to test with and figured ID was mandatory for my data structure..
OK. So you wanted to hide private members. That's not easy with objects. Have a look at Learning JavaScript Design Patterns and JavaScript Patterns Collection. Often the simplest way to do it is with a naming convention, e.g. members beginning with '_' should be treated privately. Can be enforced with JSDoc @private tag.

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.