如果对象不存在,则将缺少的属性添加到具有空值的对象

时间:2015-04-25 14:03:16

标签: javascript

我有一组具有不同属性的对象:

var arr = [];

var obj_1 = {
    'key_a': 'value_a',
    'key_b': 'value_b'
};

arr.push(obj_1);

var obj_2 = {
    'key_a': 'value_a',
    'key_b': 'value_b',
    'key_c': 'value_c'
};

arr.push(obj_2);

如果数组中的每个对象都不存在,我如何自动将新密钥(key_c)或任何其他密钥添加到数组中的每个对象?

所以数组看起来像这样:

    [
        {
            'key_a': 'value_a'
            'key_b': 'value_b'
            'key_c': ''
        },
        {
            'key_a': 'value_a'
            'key_b': 'value_b'
            'key_c': 'value_c'
        }
    ]

请注意:我正在构建一个Web scraper,未知的键/属性将添加到对象中,并在foreach循环中推送到数组。

5 个答案:

答案 0 :(得分:5)

  

如果新密钥(key_c)或任何其他密钥不存在,我如何自动将新密钥(key_c)或任何其他密钥添加到数组中的每个对象并使用空值?

你必须旋转数组,检查每个对象是否还有他们没有的密钥,并添加它们,这将是一种痛苦。

相反,您可以拥有一个原型对象,其中包含所有具有默认值的属性,并在所有具体对象后面使用该原型。当您了解新密钥时,使用默认值将它们添加到原型中,并且它们似乎可以追溯地在所有先前对象上神奇地出现(因为您正在修改它们背后的原型)。稍后从对象获取属性时,他们将使用自己的值来获取他们拥有的属性,并使用原型中的默认值来表示他们不具备的属性。

要使用其他对象作为原型创建对象,请使用while (<$fh>) { my @data = split /,/, $_, 5; }

Object.create

如果你正在接收你需要从其他地方跟踪的对象(例如,你没有创建它们),你可以使用一个函数来创建一个对象,使用&#34;默认值&#34 ;然后复制您收到的对象的任何属性。这也是一个标记您尚未了解的新属性并为其设置默认值的机会:

obj = Object.create(defaults); // defaults is the prototype object to use

直播示例:

&#13;
&#13;
var defaults = {};
var list = [];

function addToList(obj) {
    // Create our entry backed by the defaults
    var entry = Object.create(defaults);

    // Loop through the new object's keys...
    Object.keys(obj).forEach(function(key) {
        // ...adding a default if it's a new key
        if (!defaults.hasOwnProperty(key)) {
            defaults[key] = /*...default value...*/;
        }
        // ...and grabbing the value
        entry[key] = obj[key];
    });

    // Put it on the list
    list.push(entry);
}
&#13;
var defaults = {};
var list = [];

function addToList(obj) {
  // Create our entry backed by the defaults
  var entry = Object.create(defaults);
  
  // Loop through the new object's keys...
  Object.keys(obj).forEach(function(key) {
    // ...adding a default if it's a new key
    if (!defaults.hasOwnProperty(key)) {
      defaults[key] = "default for " + key;
    }
    // ...and grabbing the value
    entry[key] = obj[key];
  });
  
  // Put it on the list
  list.push(entry);
}

addToList({a: "a0", b: "b0"}); // Has a and b
addToList({a: "a1", c: "c1"}); // Has a and c
addToList({b: "b2", d: "d2"}); // Has b and d

list.forEach(function(entry, index) {
  snippet.log("Object #" + index + ":");
  Object.keys(defaults).forEach(function(key) {
    snippet.log(key + " = " + entry[key]);
  });
});
&#13;
&#13;
&#13;

答案 1 :(得分:2)

通过扩展函数实现属性缺失的一种迂回方式,如下所示:

(function() {
    'use strict';    

    var commonPrototype = new function() {
        var self = this;
        self.getProp = function(key) {
            if (this.hasOwnProperty(key)) {
                return this[key];
            }
            
            return 'DEFAULT';  //change to empty string if you want
        }
    };
    
    var a = [];
    
    var lit = {
        'key1' : 'key1Value',
        'key2' : 'key2Value'
    };
    
    extend(lit, commonPrototype);    
    a.push(lit);
    
    var lit2 = {
        'key1' : 'key1Value',
        'key2' : 'key2Value',
        'key3' : 'key3Value'
    };    
    extend(lit2, commonPrototype);
    a.push(lit2);
    
    console.log(a[1].getProp('key3'));     //return actual lit2 key3 value
  
    console.log(a[0].getProp('key3'));    //return the default (DEFAULT or whatever you want) when it's missing
    
    function extend(o, p) {
        o.getProp = p.getProp;        
    }
        
}());

这里唯一的问题是默认访问者无法正常工作,但您可以使用getProp(keyName)获取值。

当使用Proxy这样的ES6时,这可以更好:

function proxify(o) {
    return new Proxy(o, {
        get : function(target, name, receiver) {
                  return (target.hasOwnProperty(name)) ? target[name] : "DEFAULT";
        }
    });
}

var l1 = proxify({ key1: '1', key2: '2'});
var l2 = proxify({ key1: '1.1', key2: '1.2', key3: '1.3'});

console.log(`l1.key3: ${l1.key3}`);
console.log(`l2.key3: ${l2.key3}`);

我希望您可以用自己的代码替换prop访问器的方式,但这样做。

自2015-04-26起,该代码可在Firefox 37+和Microsoft Edge(以前的Spartan)上执行。

答案 2 :(得分:2)

我创建了一个特殊对象来充当容器。此特殊对象将存储推入其中的对象的键以及对象。

一旦用户想要从中检索对象,该对象将更新存储对象的键,以确保所有对象具有正确值的相同键。

{{1}}

您可以为此对象添加功能以改进它。

<强> Fiddle

希望它有所帮助。

答案 3 :(得分:0)

不确定我是否完全理解您的问题,但如果您想要将对象添加到对象中,如果他们没有这样做,您可以这样做:

var obj_1 = {
    'key_a': 'value_a',
    'key_b': 'value_b'
};
if(!obj_1.hasOwnProperty("key_c"))
    obj_1.key_c=undfined;

这个想法是你正在检查对象属性是否存在而不是未定义的值。

其他选项是致电Object.keys(obj_1)//["key_a","key_b"] 并检查所需的密钥是否在数组中。

答案 4 :(得分:0)

这是一个解决方案:

var keysSet = new Set();
var pushWithFill = function(arr, newObject) {
    // add keys from the new obj to the dictionary
    // and add missing properties to this object
    keysSet.forEach(function(key){
        if (!newObject.hasOwnProperty(key)) {
            newObject[key] = '';
        }
    });
    for (var property in newObject) {
        keysSet.add(property);
    }

    // process all stored objects to add keys from the new one to them
    arr.forEach(function(storedObj, index){
        for (var property in newObject) {
             if (!storedObj.hasOwnProperty(property)) {
                    storedObj[property] = '';
             } 
        }
    });

    arr.push(newObject);
};

使用示例:

var arr = [];

var obj_1 = {
    'key_a': 'value_a',
    'key_b': 'value_b'
};
var obj_2 = {
    'key_a': 'value_a',
    'key_b': 'value_b',
    'key_c': 'value_c'
};
var obj_3 = {
    'key_a': 'value_a'
}

pushWithFill(arr, obj_1);
pushWithFill(arr, obj_2);
pushWithFill(arr, obj_3);

结果:

[{
        " key_a " : " value_a ",
        " key_b " : " value_b ",
        " key_c " : " "
    }, {
        " key_a " : " value_a ",
        " key_b " : " value_b ",
        " key_c " : " value_c "
    }, {
        " key_a " : " value_a ",
        " key_b " : " ",
        " key_c " : " "
    }
]