Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the simplest approach to check existence of deeply-nested object property in JavaScript? [duplicate]

I have to check deeply-nested object property such as YAHOO.Foo.Bar.xyz.

The code I'm currently using is

if (YAHOO && YAHOO.Foo && YAHOO.Foo.Bar && YAHOO.Foo.Bar.xyz) {
    // operate on YAHOO.Foo.Bar.xyz
}

This works, but looks clumsy.

Is there any better way to check such deeply nested property?

like image 770
Morgan Cheng Avatar asked Aug 03 '11 13:08

Morgan Cheng


People also ask

How do you check if a property exists in an object in JavaScript?

JavaScript provides you with three common ways to check if a property exists in an object: Use the hasOwnProperty() method. Use the in operator. Compare property with undefined .

How do you get the properties of nested objects?

To access a nested attribute, you need to specify its name and then search through the object. When you don't know the exact name before hand, or a user is the one who provides the name for you. Then dynamically searching through the data structure is required.

Which method is the way to see all the properties of a specified JavaScript object in the console?

The getOwnPropertyNames function can be used to enumerate over all properties of the passed in object, including those that are non-enumerable. Then a simple typeof check can be employed to filter out non-functions.

What is nested object in JavaScript?

The basic definition of an object in JavaScript is a container for named values called properties (keys). Sometimes, we need to create an object inside another object. In this case, it's called a nested object.


5 Answers

If you expect YAHOO.Foo.Bar to be a valid object, but want to make your code bulletproof just in case it isn't, then it can be cleanest to just put a try catch around it and let one error handler catch any missing segment. Then, you can just use one if condition instead of four that will detect if the terminal property exists and a catch handler to catch things if the intermediate objects don't exist:

try {     if (YAHOO.Foo.Bar.xyz) {         // operate on YAHOO.Foo.Bar.xyz } catch(e) {     // handle error here } 

or, depending upon how your code works, it might even just be this:

try {     // operate on YAHOO.Foo.Bar.xyz } catch(e) {     // do whatever you want to do when YAHOO.Foo.Bar.xyz doesn't exist } 

I particularly use these when dealing with foreign input that is supposed to be of a particular format, but invalid input is a possibility that I want to catch and handle myself rather than just letting an exception propagate upwards.

In general, some javascript developers under-use try/catch. I find that I can sometimes replace 5-10 if statements checking input with a single try/catch around a larger function block and make the code a lot simpler and more readable at the same time. Obviously, when this is appropriate depends upon the particular code, but it's definitely worth considering.

FYI, if the usual operation is to not throw an exception with the try/catch, it can be a lot faster than a bunch of if statements too.


If you don't want to use the exception handler, you can create a function to test any arbitrary path for you:

function checkPath(base, path) {     var current = base;     var components = path.split(".");     for (var i = 0; i < components.length; i++) {         if ((typeof current !== "object") || (!current.hasOwnProperty(components[i]))) {             return false;         }         current = current[components[i]];     }     return true; } 

Example usage:

var a = {b: {c: {d: 5}}}; if (checkPath(a, "b.c.d")) {     // a.b.c.d exists and can be safely accessed } 
like image 133
jfriend00 Avatar answered Oct 08 '22 02:10

jfriend00


var _ = {};  var x = ((YAHOO.Foo || _).Bar || _).xyz; 
like image 39
Kernel James Avatar answered Oct 08 '22 02:10

Kernel James


Consider this utility function:

function defined(ref, strNames) {
    var name;
    var arrNames = strNames.split('.');

    while (name = arrNames.shift()) {        
        if (!ref.hasOwnProperty(name)) return false;
        ref = ref[name];
    } 

    return true;
}

Usage:

if (defined(YAHOO, 'Foo.Bar.xyz')) {
    // operate on YAHOO.Foo.Bar.xyz
}

Live demo: http://jsfiddle.net/DWefK/5/

like image 40
Šime Vidas Avatar answered Oct 08 '22 00:10

Šime Vidas


If you need to check the correctness of the path, rather than the existance of the "xyz" member on the "YAHOO.Foo.Bar" object, it will probably be easiest to wrap the call in a try catch:

var xyz;
try {
    xyz = YAHOO.Foo.Bar.xyz;
} catch (e) {
    // fail;
};

Alternately, you can do some string-kong-fu-magicTM:

function checkExists (key, obj) {
    obj = obj || window;
    key = key.split(".");

    if (typeof obj !== "object") {
        return false;
    }

    while (key.length && (obj = obj[key.shift()]) && typeof obj == "object" && obj !== null) ;

    return (!key.length && typeof obj !== "undefined");
}

The use as follows:

if (checkExists("YAHOO.Foo.Bar.xyz")) {
    // Woo!
};
like image 26
Matt Avatar answered Oct 08 '22 00:10

Matt


This problem is solved quite beautifully by coffeescript (which compiles down to javascript):

if YAHOO.Foo?.Bar?.xyz
  // operate on YAHOO.Foo.Bar.xyz
like image 28
Albert Wu Avatar answered Oct 08 '22 02:10

Albert Wu