最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

variables - Can you create an object in Javascript without declaring every value, and how? - Stack Overflow

programmeradmin1浏览0评论

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 badges
Add a ment  | 

8 Answers 8

Reset to default 4

If 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.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论