0

Because this approach of checking every single object along the way is getting a bit silly:

const saved = profile && 
  profile.content && 
  question &&
  question.subject && 
  profile.content[question.subject] && 
  profile.content[question.subject].saved 
  ? 
  profile.content[question.subject].saved.includes(question._id) 
  : false

Something like this would be bless:

const value = profile.content[question.subject].saved.includes(question._id)

if(value === defined) {
  // cool
}

I'm sure there's something lovely and ES6'y that older questions have missed. Cheers!

dan674
  • 1,848
  • 2
  • 15
  • 21

2 Answers2

0

Until now the shortest is probably:

(((( profile || {}) .content || {})[question.subject] || {}).saved || {}).includes(question._id) || false

In a future version of javascript one can do:

 profile?.content?[question.subject]?.saved.includes(question._id)  || false
Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
  • Ooo, any more information about this future addition? I'm using babel on all my projects so maybe its (almost) within reach – dan674 Apr 24 '18 at 19:23
  • @dan674 https://github.com/tc39/proposal-optional-chaining/blob/master/README.md – Jonas Wilms Apr 24 '18 at 19:34
  • 1
    One can already use a nested destructuring assignment: `const {content: {[question.subject]: {saved} = {}} = {}} = profile;`, then use `saved`. – Sebastian Simon Apr 24 '18 at 19:38
  • @xufox i dont think that this is more readable ... – Jonas Wilms Apr 24 '18 at 20:12
  • @JonasW. It’s just an alternative. However, it is more compact, and is in some sense even more readable, as the expected structure of the object `profile` is written out quite cleanly on the left-hand side. – Sebastian Simon Apr 24 '18 at 20:38
0

I would just define a function get, that lets you pass in a string with the path you want:

const get = (o, p) =>
         p.split('.').reduce((xs, x) => (xs && xs[x]) ? xs[x] : undefined, o)

    
const testData = {
    a: {
        b: {
            c: 'd',
            e: 'f',
            h: 'i'
        },
        j: 'k'
   }
}

console.log(get(testData, 'a.b.c'));
console.log(get(testData, 'd'));
console.log(get(testData, 'a.b.e'));
dave
  • 62,300
  • 5
  • 72
  • 93
  • definitely handy, but I feel like in my use case where I want to check properties dynamically (e.g. content[question.subject] ) this will still be a bit messy and I'll have to run get() a couple times – dan674 Apr 24 '18 at 19:46