I want to do the following:
var Room = function(name, north, south, east, west) {
this.name = name;
this.north = north;
this.south = south;
this.west = west;
this.east = east;
}
Where north, south, east and west is just a flag saying if there is a door there.
When I create an object I have to do this:
var bedroom = new Room('Bedroom', true, false, false, false);
I was wondering if there is a way so that I can just say which directions have a true value such as:
var bedroom = new Room({
name: 'Bedroom',
north: true
});
With south, east, and west being false. This way if I were to have say 20 different options I would only have to specify the ones I care about, instead of having a long declarations with a lot of false and '' values and I wouldn't need to remember which order they were suppose to be in (north, south, east, west? or north, east, south, west?),
I want to do the following:
var Room = function(name, north, south, east, west) {
this.name = name;
this.north = north;
this.south = south;
this.west = west;
this.east = east;
}
Where north, south, east and west is just a flag saying if there is a door there.
When I create an object I have to do this:
var bedroom = new Room('Bedroom', true, false, false, false);
I was wondering if there is a way so that I can just say which directions have a true value such as:
var bedroom = new Room({
name: 'Bedroom',
north: true
});
With south, east, and west being false. This way if I were to have say 20 different options I would only have to specify the ones I care about, instead of having a long declarations with a lot of false and '' values and I wouldn't need to remember which order they were suppose to be in (north, south, east, west? or north, east, south, west?),
Share Improve this question asked Feb 23, 2015 at 17:34 Jonathan Owen ChuteJonathan Owen Chute 906 bronze badges8 Answers
Reset to default 4If you really need separate instance variables for north
, south
, east
and west
, I'd suggest something like this where you can pass just the directions that you care about in a space delimited string. This makes the calling code much simpler since you don't have to pass anything for the directions that don't exist.
var Room = function(name, directions) {
this.name = name;
this.north = this.south = this.west = this.east = false;
directions = directions.split(" ");
directions.forEach(function(item) {
this[item] = true;
})
}
var bedroom = new Room('Bedroom', 'north south');
Or, your object approach works fine too:
var Room = function(name, directions) {
this.name = name;
this.north = this.south = this.west = this.east = false;
for (var dir in directions) {
this[dir] = directions[dir];
}
}
var bedroom = new Room('Bedroom', {north: true, south: true});
A third approach is to use flags (often used in C/C++). This allows you to pass an arbitrary number of flags in a single value:
var Room = function(name, directions) {
this.name = name;
this.directions = directions;
}
Room.prototype = {
isNorth: function() { return this.directions & Room.north},
isSouth: function() { return this.directions & Room.south},
isWest: function() { return this.directions & Room.west},
isEast: function() { return this.directions & Room.east},
};
Room.north = 1;
Room.south = 2;
Room.east = 4;
Room.west = 8;
var bedroom = new Room('Bedroom', Room.north | Room.south);
JavaScript Objects
Add in a default value with the ||
operator
var Room = function(name, north, south, east, west) {
this.name = name;
this.north = north || false;
this.south = south || false;
this.west = west || false;
this.east = east || false;
}
This will tell it to use east
if data was supplied for it or use false if east
turns out to be undefined
.
var Room = function (options) {
this.name = options.name;
var cardinals = ['north', 'south', 'east', 'west'];
// Check your directions param for each of the cardinal directions
// that you want to allow
cardinals.forEach(function (direction) {
if (typeof options[direction] !== 'undefined') {
this[direction] = options[direction];
} else {
this[direction] = false;
}
});
};
var room = new Room({ name: 'Bedroom', north: true, south: true });
You can use "for .. in ..." loop to iterate input object with params. Example:
Room = function(options) {
for (var key in options) {
this[key] = options[key];
}
}
var bedroom = new Room({
name: 'Bedroom',
north: true
});
You can use the ||
operator
e.g.
var Room = function(name, directions) {
this.name = name;
this.north = directions.north || false;
this.south = directions.south || false;
this.west = directions.west || false;
this.east = directions.east || false;
}
then when you call var r = new Room("something", {north:true});
all the other values will be set to false.
You can use some sort of subclass.
In main class you put all default values.
function AbstractRoom(name, north, south, east, west){
this.name = name;
this.north = north;
this.south= south;
this.east= east;
this.west= west;
}
In your sub-class you put your values
function RoomNorth(name){
AbstractRoom.call(this, name, true, false, false, false);
}
in this case
var myNorthRoom = new RoomNorth('AGoodName');
where
myNorthRoom.north <-- true
myNorthRoom.south <-- false
What about:
var Room = function( name, directions ) {
this.name = name;
this.north = directions.north || false;
this.south = directions.south || false;
this.west = directions.west || false;
this.east = directions.east || false;
}
And then calling the constructor like:
var bedroom = new Room( 'Bedroom', { 'north': true } );
If you don't define a direction the || operator will make it false.
Here is another way using a "chaining" pattern (it's not a builder per-se):
function Room (name) {
this.name = name;
}
Room.prototype = {
north: function (v) {
if (arguments.length > 0 } { this._north = v; return this; }
else { return this._north; }
},
south: function (v) {
if (arguments.length > 0 } { this._south = v; return this; }
else { return this._south; }
},
// .. rest of getter-setters
// The prototype can be used for defaults and/or lifting
_north: false,
_south: false,
// .. rest of defaults
}
var room = new Room("bedroom")
.north(true)
.south(true); // => the Room object
var hasNorth = room.north(); // => true
Some people might not like this pattern - and especially this implementation - because it changes the return type of the getter/setter to be "sometimes-chainable" and "sometimes-return-the-value", like some jQuery methods (eg. $.val
).
It also requires / encourages that the directions (eg. "north") be accessed via getter methods. Defining properties doesn't allow such chaining syntax.