2

I would ask about best practice for conditionals on objects in JS.

fexp:

if (a.b.c.d == 1)

but if i don't know if that object has correct structure i need to do conditional like this:

if(a && a.b && a.b.c && a.b.c.d && a.b.c.d == 1)

is it best way to check values? Try catch only? Universal method like this:

javascript test for existence of nested object key

is not best way because i need to change definition of my conditionals. I can;t use in this example rules like this: if (a.b[1].c.d)

i need remember about all path, channge to string etc...

I am looking for good solution my first conditionals: if (a.b.c.d ==1 )

without change it or changed it in simply way like if (is(a.b.c.d) == 1)

try catch are ok but no for big body of conditionals :(

Community
  • 1
  • 1
Kim Yu
  • 205
  • 2
  • 9

3 Answers3

0

You could just check every value and keep checking until you run out of depth. I have written a little helper function below that will automate this process:

function checkDeep(object){
    for(var i = 1; i < arguments.length; i++){
        if(typeof object[arguments[i]] !== "undefined"){
            /* Check the type of the nested value - if not undefined,
             * set it to `object` and continue looping. */
            object = object[arguments[i]]
        } else {
            /* If it is not undefined, return false. */
            return false;
        }
    }
    /* If we made it past the loop, all the values exist and we return true. */
    return true;
}

You can add as many variables to this as you like at the end and see if they are nested within the previous value. If it hits a break in the chain anywhere, it will return false. So its definition would be:

checkDeep(object, var1[, var2, var3, ...]);

It would be called as such:

checkDeep({a:{b:{c:['d']}}}, 'a', 'b', 'c'); // true
checkDeep({a:{b:{c:['d']}}}, 'a', 'c', 'c'); // false

If you want the value at that position, just return object at the end of the function instead of return true.

function checkDeep(object){
    for(var i = 1; i < arguments.length; i++){
        if(typeof object[arguments[i]] != 'undefined') object = object[arguments[i]]
        else return false;
    }
    return true;
}

var object = {a:{b:{c:['d']}}};

document.write("Order a,c,c in '{a:{b:{c:['d']}}}' is " + (checkDeep(object, 'a', 'c', 'c') ? "true" : "false") + "<br />");
checkDeep(object, 'a', 'c', 'c'); // false

document.write("Order a,b,c in '{a:{b:{c:['d']}}}' is " + (checkDeep(object, 'a', 'b', 'c') ? "true" : "false") + "<br />");
checkDeep(object, 'a', 'b', 'c'); // true
somethinghere
  • 16,311
  • 2
  • 28
  • 42
  • bad... i don't need function with few arguments - i have one simply bad path: a.b.c.d bad = because object "a" hasn't key "b" that's all so i wanna use only this path a.b.c.d = wrong object and take it in exp function witch give me false or true – Kim Yu Jun 12 '15 at 18:44
0

you can try:

function get_value(variable, elements) {
   if (elements.length === 0) {
      return variable;
   }
   var key = elements.shift();
   return variable[key] && get_value(variable[key], elements); 
}

var a={b:{c:{d:{e:24}}}}

console.log(get_value(a, ['b','c','d','e'])) //24

console.log(get_value(a, ['b','c','d','e', 'f'])) //undefined

Only for check if the value exist:

function check(variable, elements) {
   if (elements.length === 0) {
      return true;
   }
   var key = elements.shift();
   return variable[key] !== undefined && check(variable[key], elements); 
}
Raúl Martín
  • 4,471
  • 3
  • 23
  • 42
  • Maybe a sneak a peek approach would be more convenient. Like just returning `true` or `false` if you can access safely or not the asked keys – axelduch Jun 12 '15 at 14:26
  • I don't think that you really need, but i added the code option. – Raúl Martín Jun 12 '15 at 14:34
  • bad... i don't need function with few arguments - i have one simply bad path: a.b.c.d bad = because object "a" hasn't key "b" that's all so i wanna use only this path a.b.c.d = wrong object and take it in exp function witch give me false or true – Kim Yu Jun 12 '15 at 18:44
  • and one more things how in your example i will check this value: if(a.b['oo-dd-zz'][3].c.d.e){} – Kim Yu Jun 12 '15 at 18:47
  • in var a={b:{c:[{d:{e:24}}]}} you can console.log(get_value(a, ['b','c', 0 ,'d','e'])) You can add the index – Raúl Martín Jun 12 '15 at 23:56
  • get_value(a, ['b','oo-dd-zz','3','c','d','e']) – Raúl Martín Jun 13 '15 at 12:38
0

CoffeeScript has the existential operator:

a?.b?.c?.d

There is an extensive disucssion on this topic, also called the "null propagation operator", on the ES6 discuss list at https://esdiscuss.org/topic/existential-operator-null-propagation-operator.