1

I'm building a text adventure to learn javascript, and I am not sure how to locate objects when using the object prototype. With the literal syntax, for example, I've defined location objects:

locations = {
    yard : {
        title: "Yard",
        description: "You are in the Yard. You can go east.",
        exits : {
            north : -1,
            east : "foyar",
            south : -1,
            west : -1
        },
        items: ["lamp"],
        points: 5
    },
        // etc..
}

and can locate info like this (for example):

currentLocation = locations[currentLocation]["exits"][direction]

... but I'm not really sure how to arrange and locate objects when I define them from a prototype:

function item(){
    this.id = undefined;
    this.title = "";
    this.description = "";
    this.points = 0;
    this.canTake = false;
}

var glasses = new item();
glasses.id = 1;
glasses.title = "Glasses";
glasses.description = "A scratched up pair of glasses. They aren't your prescription";
glasses.points = 10;
glasses.canTake = true;

What's the best way to structure and refer to my data here? (And are there particular advantages to using the literal or prototype approach in this context?)

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
drenl
  • 1,321
  • 4
  • 18
  • 32
  • 4
    For pure data objects that share neither methods nor (default) data properties, there's no benefit of using prototypes. Go with plain object literals. – Bergi Dec 19 '13 at 00:35
  • yeah it does look that way. but for future reference, is there a proper way to organize and refer to the prototype based objects should I want to reference them in some manner like I've described? – drenl Dec 19 '13 at 00:48
  • You'd pass the data as arguments to the constructor, either as multiple parameters or even as a whole object literal. – Bergi Dec 19 '13 at 01:37

1 Answers1

0

If you have multiple object instances of the same type (as item seems to be) and they have behaviour then you'll put the behaviour on the prototype. This because it's shared among instances and will save you cpu and memory when creating/storing them. It'll also allow you to re use similar item logic by using inheritance (an Employee is a Person so name, age and gender can be initialised by Person and re used by Employee without copy and pasting the code)

For example: if your item has a useIt function then a match will behave differently from a lighter as a match can be used for a short time once and a lighter can be used multiple times and for a longer time (until it gets too hot and explodes).

More on how to create instances and use prototype can be found in this answer.

Here is some sample code how you could create Location and Item:

//constructor for Item
var Item=function(args){
  //set canuse default to true or whats
  //  passed in args
  this.canUse=(typeof args.canUse==="undefined")?
    true:args.canUse;
  //cannot create an Item without description
  //  description doesn't have a default value
  if(typeof args.description==="undefined")
    throw new Error("Cannot create an item without description");
  this.description = args.description;
  //default value for usedTimes is 0 but can be an old
  // lighter that's been hused hundreds of times
  this.usedTimes=(typeof args.usedTimes==="undefined")?
    0:args.usedTimes;
};
//behavior on the prototype
Item.prototype.useIt=function(){
  this.usedTimes++;
};

//specify a match (should add jsdoc here so you know what args can be passed)
var Match=function(args){
  //re use Item code
  Item.call(this,args);
  //how powerfull is the Match (defaults to 5)
  this.burnPower=(typeof args.burnPower==="undefined")?
    5:args.burnPower
};
//Match behavior
Match.prototype.useIt=function(args){
  if(this.usedTimes!==0){
    //tell user it's used up
    return;
  }
 if(args.strikeOn && args.strikeOn.strikableSurface!==true){
    //tell user to to define a surfice to strike the match on
    return;
  }
  if(!args.useOn){
    //tell user to use it on ...
  }
  if(args.useOn.toBurn<=this.burnPower){
    //burn it and call Item to indicate it's used
    Item.prototype.useIt.call(this);
  }
};

//constructor for location
var Location = function(args){
  this.type=args.type;
  if(typeof this.type==="undefined")
    throw new Error("Cannot create a location without specifying type");
  this.title=(typeof args.title==="undefined")?
    args.type:args.title;
  //other stuff where type is mandatory
  this.items=[];
}
Location.prototype.addItem=function(item){
  this.items.push(item);
};
var args={},locations = {};

var loc=new Location({type:"Yard"});
loc.addItem(new Match({description:"A small match"}));
locations[loc.type]=loc;
console.log(locations);
Community
  • 1
  • 1
HMR
  • 37,593
  • 24
  • 91
  • 160
  • thanks. this gives me a lot to learn about. I'm not sure, however, if it addresses my primary question about how to organize and refer to object-from-prototype data. – drenl Dec 19 '13 at 01:14
  • @GregoryTippett not sure what that means, but if you create glasses with `glasses=new Glasses({type:Item.glasses});` then the useIt would refer to it self by using `this` for example: `Glasses.prototype.useIt=function(){Item.prototype.useIt.call(this); if(this.usedTimes)...}` It is explained in the link in the answer. Best would be for an Item constructor to handle Item specific things (like usedTimes++ when useIt is called) and Glasses to inherit from Item with extending Glasses specific behaviour. – HMR Dec 19 '13 at 01:27
  • @GregoryTippett I've added some sample code, hope that helps. – HMR Dec 19 '13 at 01:55
  • cool! ok I'll have to look this over. thanks for all the info. – drenl Dec 19 '13 at 02:06