Можете ли да създадете обект в Javascript, без да декларирате всяка стойност, и как?

Искам да направя следното:

var Room = function(name, north, south, east, west) {
    this.name = name;
    this.north = north;
    this.south = south;
    this.west = west;
    this.east = east;
}

Където север, юг, изток и запад е просто знаме, което казва дали там има врата.

Когато създавам обект, трябва да направя следното:

var bedroom = new Room('Bedroom', true, false, false, false);

Чудех се дали има начин, така че да мога просто да кажа кои посоки имат истинска стойност, като например:

var bedroom = new Room({
    name: 'Bedroom',
    north: true
});

С юг, изток и запад стават фалшиви. По този начин, ако трябваше да имам да речем 20 различни опции, ще трябва да посоча само тези, които ме интересуват, вместо да имам дълги декларации с много false и '' стойности и не би трябвало да си спомням в кой ред трябваше да бъдат (север, юг, изток, запад? или север, изток, юг, запад?),


person Jonathan Owen Chute    schedule 23.02.2015    source източник


Отговори (8)


Ако наистина имате нужда от отделни променливи на екземпляр за north, south, east и west, бих предложил нещо подобно, където можете да подадете само указанията, които ви интересуват, в низ, разделен с интервал. Това прави кода за повикване много по-прост, тъй като не е нужно да предавате нищо за указанията, които не съществуват.

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');

Или вашият обектен подход също работи добре:

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});

Третият подход е да се използват флагове (често използвани в C/C++). Това ви позволява да подадете произволен брой флагове в една стойност:

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);
person jfriend00    schedule 23.02.2015
comment
Ами ако и северът, и югът трябва да са верни? - person j08691; 23.02.2015
comment
@j08691 - Първоначално не разбрах, че това е изискване. Модифицирах отговора си, за да подкрепя това сега. - person jfriend00; 23.02.2015
comment
Разделеният с интервал низ е малко идиосинкратичен (т.е. сега е начинът, по който бихте направили нещата в много други ситуации), но в този случай е някак симпатичен. - person Nate; 23.02.2015
comment
Благодаря, след като пробвах другите, този ми се стори най-добър! - person Jonathan Owen Chute; 23.02.2015
comment
@JonathanOwenChute - добавих трета версия, която използва двоични флагове. - person jfriend00; 23.02.2015
comment
@jfriend00 - Благодаря, обектният подход има най-логичния смисъл за мен и работи като чар, оценявам цялата работа! - person Jonathan Owen Chute; 23.02.2015

JavaScript обекти

Добавете стойност по подразбиране с оператора ||

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;
}

Това ще му каже да използва east, ако за него са предоставени данни, или да използва false, ако east се окаже undefined.

person Harben    schedule 23.02.2015
comment
Мислех, че целият смисъл на въпроса е да не се налага да преминавам всички указания наведнъж в конструктора. Това изглежда някак глупаво. - person jfriend00; 23.02.2015
comment
Просто внимавайте да използвате този начин за присвояване на стойности по подразбиране с true и false. Ще работи в тази посока, но не можете да присвоите неверни стойности с верни стойности по подразбиране по този начин. - person Nate; 23.02.2015

Моля, споменете механизма за език/регекс и включете опитите си за проблема във вашия въпрос.
person Alex Kopachov    schedule 23.02.2015
comment
Мисля, че ще премина към този подход, след като for .. of .. се поддържа навсякъде. Харесва ми начина, по който всяка друга стойност е undefined, но използването на for .. in .. има проблеми. - person Hector; 21.04.2015

Можете да използвате оператора ||

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;
}

тогава, когато извикате var r = new Room("something", {north:true});, всички останали стойности ще бъдат зададени на false.

person Hector    schedule 23.02.2015

Можете да използвате някакъв вид подклас.

В главния клас поставяте всички стойности по подразбиране.

function AbstractRoom(name, north, south, east, west){
    this.name = name;
    this.north = north;
    this.south= south;
    this.east= east;
    this.west= west;
}

Във вашия подклас вие поставяте своите ценности

function RoomNorth(name){
  AbstractRoom.call(this, name, true, false, false, false);
}

в такъв случай

var myNorthRoom = new RoomNorth('AGoodName');

където

myNorthRoom.north <-- true
myNorthRoom.south <-- false
person Matteo Rubini    schedule 23.02.2015

Какво относно:

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;
}

И след това извикване на конструктора като:

var bedroom = new Room( 'Bedroom', { 'north': true } );

Ако не дефинирате посока, || ще го направи невярно.

person armellini13    schedule 23.02.2015

Ето друг начин, използващ модел за "верижно свързване" (той не е строител сам по себе си):

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

Някои хора може да не харесат този модел - и особено тази реализация - защото променя типа на връщане на getter/setter да бъде "sometimes-chainable" и "sometimes-return-the-value", като някои jQuery методи (напр. $.val ).

Той също така изисква/насърчава посоките (напр. "север") да бъдат достъпни чрез getter методи. Дефинирането на свойства не позволява такъв синтаксис на верижно свързване.

person user2864740    schedule 23.02.2015

person    schedule
comment
Не се препоръчва да се итерира масив в Javascript с for (var direction in cardinals), тъй като това итерира всички свойства на масива, а не само елементите на масива и може да включва всякакви изброими методи за полифил или персонализирани методи, добавени към обекта Array. Вместо това използвайте .forEach() или стила for (var i = 0; i < cardinals.length; i++). - person jfriend00; 23.02.2015
comment
Съгласен! Не знам защо използвах този начин първоначално; разсеяност? Актуализирах моя пример за бъдещи поколения. - person Nate; 24.02.2015