How to get the properties of a JavaScript object without errors

Published: | Updated: | by Julian Knight Reading time ~3 min.
📖 Kb | 📎 Development | 🔖 javascript, ecmascript

You cannot natively request chained properties of a JavaScript object without the possibility of an error. This utility function allows you to get any properties, no matter how they are nested.

Let’s say that we have an object like that shown in the example.

We can use the function to get any property, including nested properties and property names with spaces very simply. We can use both dot and bracket notation as shown in the tests.

The function will always either return the value of the given property or undefined. It will not return an error.

Example Object 🔗︎

We can use this for reference

{
    "a":"fred",
    "b":"yup",
    "c": {
        "c1":1,"c2":2
    },
    "d":{
        "d 1":1,
        "d 2": {
            "d 2a":"a",
            "d 2b":"b"
        }
    }
}

Code 🔗︎

/** Get a nested property from an object without returning any errors.
 * If the property or property chain doesn't exist, undefined is returned.
 * Property names with spaces may use either dot or bracket "[]" notation.
 * Note that bracketed property names without surrounding quotes will fail the lookup.
 *      e.g. embedded variables are not supported.
 * @param {object} obj The object to check
 * @param {string} prop The property or property chain to get (e.g. obj.prop1.prop1a or obj['prop1'].prop2)
 * @returns {*|undefined} The value of the objects property or undefined if the property doesn't exist
 */
function getProp(obj, prop) {
    if (typeof obj !== 'object') throw 'getProp: obj is not an object'
    if (typeof prop !== 'string') throw 'getProp: prop is not a string'

    // Replace [] notation with dot notation
    prop = prop.replace(/\[["'`](.*)["'`]\]/g,".$1")

    return prop.split('.').reduce(function(prev, curr) {
        return prev ? prev[curr] : undefined
    }, obj || self)
} // --- end of fn getProp() --- //

Tests 🔗︎

const testObj = {"a":"fred","b":"yup","c":{"c1":1,"c2":2},"d":{"d 1":1,"d 2":{"d 2a":"a", "d 2b":"b"}}}
let x = getProp(testObj, 'b')
console.log( 'getProp: "b" ', x )
console.assert(x==='yup', 'Expected b === "yup"')

x = getProp(testObj, 'e')
console.log( 'getProp: "e" ', x )
console.assert(x===undefined, 'Expected e === undefined')

x = getProp(testObj, 'b.b1')
console.log( 'getProp: "b.b1" ', x )
console.assert(x===undefined, 'Expected b.b1 === undefined')

x = getProp(testObj, 'c')
console.log( 'getProp: "c" ', x )
// console.assert doesn't seem to work for comparing objects
//console.assert(x==={"c1": 1, "c2": 2}, 'Expected c === {c1: 1, c2: 2}')

x = getProp(testObj, 'c.c1')
console.log( 'getProp: "c.c1" ', x )
console.assert(x===1, 'Expected c.c1 === 1')

x = getProp(testObj, 'c["c1"]')
console.log( 'getProp: "c["c1"]" ', x )
console.assert(x===1, 'Expected c["c1"] === 1')

x = getProp(testObj, 'd.d 1')
console.log( 'getProp: "d.d 1" ', x )
console.assert(x===1, 'Expected d.d 1 === "b"')

x = getProp(testObj, 'd.d 2.d 2b')
console.log( 'getProp: "d.d 2.d 2b" ', x )
console.assert(x==='b', 'Expected d.d 2.d 2b === "b"')

x = getProp(testObj, 'd["d 2"].d 2b')
console.log( 'getProp: "d["d 2"]d 2b" ', x )
console.assert(x==='b', 'Expected d["d 2"]d 2b === "b"')

comments powered by Disqus