Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript: Adding a nested property to an object that may not exist

Suppose I have a json object in which I record the number of visitors to my site, grouped by browser / version.

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

To increment a particular browser, I need to check if several keys exist, and if not, create them.

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

The deeper my data structure the crazier things get.

It feels like there must be a neater way to do this in javascript. There's always a neater way. Can anyone enlighten me here?

like image 842
roryok Avatar asked Oct 25 '25 13:10

roryok


2 Answers

This shorter code should do the trick:

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

Note that you were using === where you should've been using = (in === {}).

Let's explain this line:

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

The last part: data.browsers = data.browsers || {} sets data.browsers to be itself if it exists. If it doesn't yet, it's set to be a new empty object.
Then, that whole value gets assigned to browsers, for ease of access.

Now, shorter code shouldn't be top priority, but in cases like this, you can make the code a lot more readable.

like image 67
Cerbrus Avatar answered Oct 28 '25 03:10

Cerbrus


You can give up the if statements and do it like this:

uap.browser = uap.browser || {}

essentially it does the same as the if only much shorter

like image 30
Tomer Avatar answered Oct 28 '25 04:10

Tomer



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!