добавление в JSON свойство, которое может или не может еще существовать - PullRequest
13 голосов
/ 26 марта 2010

скажем, я хочу сделать это:

  var dashboard = {};
  var page = "index";

  $('.check').click(function(){ 
    $(this).toggleClass("active").siblings().slideToggle('slow', function() {
        dashboard['pages'][page][$(this).closest('li').attr("id")]['show'] = $(this).is(":hidden") ? 'collapsed' : 'expanded';
    });
  }

Я получаю сообщение об ошибке:

Dashboard.pages не определено

Есть ли возможность динамически добавлять pages и последующие дочерние элементы, не выполняя работу по проверке, чтобы определить, определено ли это сначала, а затем, если это не так:

   dashboard['pages'] = {};

потому что иногда они могут уже существовать, и мне не нужно сначала проверять дерево, я просто хочу строить ветви по мере необходимости

EDIT Я изменил pagename на page, чтобы показать, что имена страниц будут меняться, а также хочу отметить, что страницы действительно могут быть чем угодно. Идея состоит в том, что у вас есть любой объект, который может содержать объекты с параметрами, не проверяя, существуют ли ветви

Похоже, $extend, как указано, это будет путь, просто не знаю, как это работает. Я должен обдумать это.

Ответы [ 7 ]

15 голосов
/ 07 апреля 2010

Определите методы get и set для Object. На самом деле его можно определить только для объекта dashboard и только для его потомков, но это легко сделать.

Object.prototype.get = function(prop) {
    this[prop] = this[prop] || {};
    return this[prop];
};

Object.prototype.set = function(prop, value) {
    this[prop] = value;
}

Выполните итерацию по вложенным свойствам, используя этот метод get(), и вызывайте set() всякий раз, когда необходимо установить значение.

var dashboard = {};

dashboard.get('pages').get('user').set('settings', 'oh crap');
// could also set settings directly without using set()
dashboard.get('pages').get('user').settings = 'oh crap';

console.log(dashboard); //​​​​​​​​​​​​​​​ {pages: {user: {settings: "oh crap"}}};

Вы также можете расширить / изменить метод get для принятия вложенных свойств в качестве отдельных аргументов или массива или строки. Используя это, вам нужно будет вызвать get только один раз:

// get accepts multiple arguments here
dashboard.get('pages', 'user').set('settings', 'something');

// get accepts an array here
dashboard.get(['pages', 'user']).set('settings', 'something');

// no reason why get can't also accept dotted parameters
// note: you don't have to call set(), could directly add the property
dashboard.get('pages.user').settings = 'something';

Обновление

Поскольку метод get обычно возвращает объект и не знает, нужен ли вам массив или какой-либо другой тип объекта, вам придется указать это самим:

dashboard.get('pages.user').settings = [];

Тогда вы можете выдвинуть элементы в массив настроек как

dashboard.get('pages.user').settings.push('something');
dashboard.get('pages.user').settings.push('something else');

Чтобы на самом деле функция get создала иерархию объектов из заданной строки, такой как pages.user, вам нужно разбить строку на части и проверить, существует ли каждый вложенный объект. Вот модифицированная версия get, которая делает именно это:

Object.prototype.get = function(prop) {
    var parts = prop.split('.');
    var obj = this;
    for(var i = 0; i < parts.length; i++) {
        var p = parts[i];
        if(obj[p] === undefined) {
            obj[p] = {};
        }
        obj = obj[p];
    }
    return obj;
}

// example use
var user = dashboard.get('pages.user');
user.settings = [];
user.settings.push('something');
user.settings.push('else');

console.log(dashboard); // {pages: {user: {settings: ["something", "else"] }}}

// can also add to settings directly
dashboard.get('pages.user.settings').push('etc');
2 голосов
/ 01 апреля 2010

Я бы сделал это с троичным оператором:

dashboard['pages'][page] = dashboard['pages'][page] ? dashboard['pages'][page] : {};

Это поможет, независимо от того, установлен он / ноль или как угодно.

1 голос
/ 10 февраля 2017

Лучшим решением для моего случая было создание прототипа объекта

 /**
 * OBJECT GET
 * Used to get an object property securely
 * @param object
 * @param property
 * @returns {*}
 */
Object.get = function(object, property) {
    var properties = property.split('.');
    for (var i = 0; i < properties.length; i++) {
        if (object && object[properties[i]]) {
            object = object[properties[i]];
        }
        else {
            return null;
        }
    }
    return object;
};

И тогда вы можете получить свою собственность вот так

var object = { step1: { step2: { step3: ['value1', 'value2'] }}}
Object.get(object, 'step1.step2.step3'); // ['value1', 'value2']
Object.get(object, 'step1.step2.step3.0'); // 'value1'
Object.get(object, 'step1.step2.step3.step4'); // null

Надеюсь, это поможет:)

1 голос
/ 26 марта 2010

Не думаю, что есть хороший встроенный способ сделать это, но вы всегда можете абстрагировать его с помощью функции.

function getProperty(obj,prop){
    if( typeof( obj[prop] ) == 'undefined' ){
        obj[prop] = {};
    }
    return obj[prop];
}

Тогда вы используете

getProperty(dashboard,'pages')['pagename']

или

getProperty(getProperty(dashboard,'pages'),'pagename');

Как уже упоминалось, $ .extend сделает это менее обременительным.

0 голосов
/ 07 апреля 2010

Ну, я думаю, тебе нужно это:

var dashBoard = new Array();
if(!dashboard['page123']) {
    dashBoard.push('page123');
} else {
...do what you want
}

Кажется, вы имеете дело с XML.

0 голосов
/ 26 марта 2010
var foo = dashboard['pages'] || {};
foo['pagename'] = 'your thing here';
dashboard['pages'] = foo;

Объяснение: первая строка проверит, является ли первое значение нулевым, неопределенным или ... ложным (не думайте, что это проблема здесь): если это так, создайте новый объект, если нет, будет используйте это.

0 голосов
/ 26 марта 2010

$. Продлить путь

function elem(a,b){
var r={'pages':{'pagename':{}}};
r.pages.pagename[a]={'show':b};
return r;
}
data={};
//inside the event handler or something:
data = $.extend(true,data,elem($(this).closest('li').attr("id"),$(this).is(":hidden") ? 'collapsed' : 'expanded'));

Но, честно говоря, это довольно грязная идея, чтобы хранить эту информацию в любом случае. Могу поспорить, что если вам понадобится эта информация позже, это можно сделать с помощью хорошего селектора или с помощью jQuery.data ()

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...