【问题标题】:Merge json-object and populate next/prev items合并 json-object 并填充下一个/上一个项目
【发布时间】:2023-03-15 20:30:01
【问题描述】:

我如何pre-填充一个包含一些 css 属性的 JSON 对象。在哪里我需要将所有 not-contained 属性添加到前一个对象,并且对所有下一个项目都相同?

我需要的语句:

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

例如,我们有一个具有以下样式的元素:

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

还有以下keyframe-alike 对象:

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

更新

T.J. Crowder answer 到目前为止看起来不错,但是 问题 是我不知道 keyframe-object 中有哪些属性...所以它可以是,还有更多/关键帧中除widthtop 之外的其他属性。

更新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...

有什么想法吗?

【问题讨论】:

标签: javascript json object for-loop keyframe


【解决方案1】:

这似乎可以满足您的要求:

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

【讨论】:

【解决方案2】:

两个想法:

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

【讨论】:

  • 到目前为止看起来不错,问题是我不知道对象中有哪些属性...所以可能是关键帧中的属性比width 和@987654335 更多@。知道如何更动态地获得它吗?
  • @yckart:首先遍历所有对象,获取所有唯一属性,解决冲突(例如,如果两个对象具有相同属性的不同值)但是适合您的问题领域。然后使用所有属性的主列表和您要用于它们的值,执行上述操作。 (#1 仍然可以应用,因为您可以随时将属性添加到 proto,它们会神奇地显示在从它继承的对象上。但是,您只能在对象时分配原型是首先创建的,因此可能无法正常工作。)
  • 嗯,看看我上次的更新,看来我的逻辑有问题......有什么想法吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多