JavaScript:将嵌套属性添加到可能不存在的对象

时间:2017-08-28 11:11:15

标签: javascript node.js object

假设我有一个json对象,我在其中记录了我的网站的访问者数量,按浏览器/版本分组。

let data = {
    browsers: {
        chrome: {
           43 : 13, 
           44 : 11
        }, 
        firefox: {
           27: 9
        }
    }
}

要增加特定浏览器,我需要检查是否存在多个密钥,如果不存在,则创建它们。

let uap = UAParser(request.headers['user-agent']);

if (typeof uap.browser !== 'undefined') {

    if (typeof data.browsers === 'undefined') 
        data.browsers = {}

    if (typeof data.browsers[uap.browser.name] === 'undefined')
        data.browsers[uap.browser.name] = {}

    if (typeof data.browsers[uap.browser.name][uap.browser.version] === 'undefined')
        data.browsers[uap.browser.name][uap.browser.version] = 0

    data.browsers[uap.browser.name][uap.browser.version] += 1;
}

我的数据结构越深入越疯狂。

感觉必须有一个更简洁的方法来在javascript中执行此操作。 总是一种更整洁的方式。谁能在这里开导我?

3 个答案:

答案 0 :(得分:2)

这个较短的代码应该可以解决问题:

if (uap.browser) { // typeof is pretty much redundant for object properties.
    const name = uap.browsers.name; // Variables for readability.
    const version = uap.browser.version;

    // Default value if the property does not exist.
    const browsers = data.browsers = data.browsers || {}; 
    const browser = browsers[name] = browsers[name] || {};
    browser[version] = browser[version] || 0;

    // Finally, increment the value.
    browser[version]++;
}

请注意,您使用===时应该使用==== {})。

让我们解释一下这句话:

const browsers = data.browsers = data.browsers || {};

最后一部分:data.browsers = data.browsers || {}data.browsers设置为自身(如果存在)。如果还没有,则将其设置为新的空对象 然后,为了便于访问,将整个值分配给browsers

现在,较短的代码不应该是最重要的,但在这种情况下,您可以使代码更具可读性。

答案 1 :(得分:0)

您可以放弃if语句,并按照以下方式执行:

uap.browser = uap.browser || {}

基本上它与if只是更短的

相同

答案 2 :(得分:0)

这里是使用Proxy()的非常简洁和通用的解决方案我有第二个解决方案,如果您不需要它,或者需要它更少浏览器,那么它就是标准ECMAscript 5。

var handler = {
    get: function (target, property) {
        if (property !== "toJSON" && target[property] === undefined) {
            target[property] = new Proxy ({}, handler);
        }
        return target[property];
    }
}
var jsonProxy = new Proxy ({}, handler);

jsonProxy.non.existing.property = 5;
jsonProxy.another.property.that.doesnt.exist = 2;
jsonProxy["you"]["can"]["also"]["use"]["strings"] = 20;

console.log (JSON.stringify (jsonProxy));

你可以用类做同样的事情,但语法更详细:

var DynamicJSON = function () {};
DynamicJSON.prototype.get = function (property) {
    if (this[property] === undefined) {
        this[property] = new DynamicJSON ();
    }
    return this[property];
};
DynamicJSON.prototype.set = function (property, value) {
    this[property] = value;
};

var jsonClass = new DynamicJSON ();
jsonClass.get("non").get("existing").set("property", 5);
jsonClass.get("you").get("have").get("to").get("use").set("strings", 20);

console.log (JSON.stringify (jsonClass));