Объединить json-объект и заполнить следующие / предыдущие элементы

Как я могу предварительно заполнить объект JSON, который содержит некоторые css-свойства. Где мне нужно добавить все свойства не содержащиеся к предыдущему объекту и то же самое для всех следующих элементов?

Заявление мне нужно:

if (property is not in object) object[property] = $('.foo').css(property);

Например, у нас есть элемент со следующим стилем:

.foo {
    top: 0;
    width: 100px;
}

И следующий keyframe-подобный объект:

var keyframe = {
    0: {
        top: 0
    },
    1000: {
        top: 100
    },
    2000: {
        width: 100
    }
};

Здесь нам нужно заполнить все предыдущие элементы, в этом случае:

  • 0: width = 0
  • 1000: width = 0

... получаем что-то вроде этого:

var keyframe = {
    0: {
        top: 0,
        width: 0
    },
    1000: {
        top: 100,
        width: 0
    },
    2000: {
        top: 100,
        width: 100
    }
};

... и далее нам нужно предварительно заполнить все следующие элементы:

  • 2000: top = 100

Что дает:

var keyframe = {
    0: {
        top: 0
    },
    1000: {
        top: 100
    },
    2000: {
        top: 100,
        width: 100
    }
};

Наш последний объект должен быть таким:

var keyframe = {
    0: {
        top: 0,
        width: 0
    },
    1000: {
        top: 100,
        width: 0
    },
    2000: {
        top: 100,
        width: 100
    }
};

Обновлять

Т.Дж. Ответ Краудера пока выглядит неплохо, однако проблема в том, что я не знаю, какие свойства находятся в keyframe-объекте ... Так что может быть, есть еще / другие свойства в ключевом кадре, чем width и top.

Обновление2

На данный момент у меня есть следующее:

var $foo = $('.foo');
for (var key in keyframe) {
    var obj = keyframe[key];
    for(var ok in obj) {
        if (!(ok in obj)) obj[ok] = $foo.css(ok);
    }
}

Но кажется, что

if (!(ok in obj)) // is always `truthy`

однако, если я сделаю это, объявив это напрямую

if (!('top' in obj)) // it works...

Любые идеи?


person yckart    schedule 16.07.2013    source источник
comment
Посмотрите этот ответ здесь, он может помочь вам stackoverflow.com/questions/736590/   -  person Banning    schedule 16.07.2013
comment
Не существует такой вещи, как объект JSON. '. Ваша проблема, похоже, не связана с JSON. У вас есть объекты JavaScript.   -  person Felix Kling    schedule 16.07.2013
comment
@FelixKling Хорошо, согласен! Это похоже на JSON. Но это все равно не помогает: P   -  person yckart    schedule 16.07.2013
comment
Конечно, но правильная терминология тоже важна;)   -  person Felix Kling    schedule 16.07.2013


Ответы (2)


Кажется, это делает то, что вы хотите:

var all = {};

$.each(keyframe, function(_, obj) {
    $.each(obj, function(k) {
        all[k] = 0;
    });
});

$.each(keyframe, function(_, obj) {
    $.each(all, function(k) {
        if(k in obj)
            all[k] = obj[k];
        else
            obj[k] = all[k];
    });
});

console.log(keyframe)
// {"0":{"top":0,"width":0},
// "1000":{"top":100,"width":0},
// "2000":{"width":100,"top":100}}
person georg    schedule 16.07.2013
comment
Здорово! Пока все выглядит хорошо, проблема в том, что мне нужно заполнить недостающие свойства из стилей элементов ... См. Этот вопрос: stackoverflow.com/questions/17678390/ - person yckart; 16.07.2013
comment
Обновление: - * - person yckart; 16.07.2013

Две мысли:

  1. Создайте объекты ключевого кадра с прототипом позади них, например:

    var proto = {top: 0, width: 100};
    var keyframe = {
        0:    Object.create(proto),  // Inherits everything
        1000: Object.create(proto, { // Inherits only width
                  top: {value: 100}
              },
        2000: Object.create(proto, { // Inherits only top
                  width: {value: 100}
              })
    };
    
  2. Сделайте это вручную, используя for-in (spec , article) и in (spec):

    var obj, key;
    for (key in keyframe) {
        obj = keyframe[key];
        if (!('top' in obj)) {
            obj.top = 0;
        }
        if (!('width' in obj)) {
            obj.width = 100;
        }
    }
    

    for-in просматривает имена перечислимых свойств объекта. in проверяет, является ли объект свойством с заданным именем (собственным или его прототипом). Выше я предполагал, что объекты в keyframe могут наследовать свойства.

    Если каждый из ваших объектов ключевого кадра является производным от других объектов (например, у них есть что-то другое, кроме Object.prototype в качестве прототипа), вы захотите добавить туда hasOwnProperty:

    var obj, key;
    for (key in keyframe) {
        if (keyframe.hasOwnProperty(key)) {
            obj = keyframe[key];
            if (!('top' in obj)) {
                obj.top = 0;
            }
            if (!('width' in obj)) {
                obj.width = 100;
            }
        }
    }
    
person T.J. Crowder    schedule 16.07.2013
comment
Пока все выглядит хорошо, проблема в том, что я не знаю, какие свойства находятся в объекте ... Так что может быть, что в ключевом кадре больше свойств, чем width и top. Есть идеи, как сделать это более динамично? - person yckart; 16.07.2013
comment
@yckart: сделайте первый проход по всем объектам, захватите все уникальные свойства, разрешите конфликты (например, если два объекта имеют разные значения для одного и того же свойства), однако это подходит для вашей проблемной области. Затем, вооружившись этим основным списком всех свойств и значений, которые вы хотите использовать для них, выполните описанное выше. (№1 все еще может применяться, потому что вы можете добавлять свойства к proto по ходу дела, и они волшебным образом проявляются на объектах, унаследованных от него. Но вы можете назначить прототип только тогда, когда объекты являются первыми создан, так что это может не сработать.) - person T.J. Crowder; 16.07.2013
comment
Ммм, посмотри на мое последнее обновление, похоже, проблема в моей логике ... Есть идеи? - person yckart; 16.07.2013