2

For a long time, I'm finding myself checking every nested object if it exists or not.

e.g. if I need

someObject.innerThing.evenInnerer.superInerer.length

I have to do

let length = someObject && someObject.innerThing && someObject.innerThing.evenInnerer && someObject.innerThing.evenInnerer.superInerer && someObject.innerThing.evenInnerer.superInerer.length;

to prevent an exception.

So I thought about a way to make it simpler and use an external method (within the class...) like this -

  const dataFetcher = (appName, failedFunc) => {
    try {
      let item = eval(appName);
      return item;
    } catch (e) {
      failedFunc && failedFunc();
      return undefined;
    }
  };

and do this =>

let length = dataFetcher("someObject.innerThing.evenInnerer.superInerer.length", optionalErrorFunc);
if(length == undefined).... 

and it's cleaner and simpler (IMO).

Are there any downsides to this..?

Thanks

Dvi N
  • 411
  • 2
  • 11

2 Answers2

3

Even if you're sure it's 100% safe, it's always good to avoid eval(), as a rule, when there are other options that are just as easy. Using try-catch to accomplish this makes things even worse, and your implementation works on the assumption that the variable whose name is being passed in is in scope from the perspective of the dataFetcher function, which makes it hard to use and unportable.

In recent versions of JavaScript, you can use conditional chaining:

const length = someObject?.innerThing?.evenInnerer?.superInnerer?.length;

There are also JS helper libraries that provide functions that help like this.

For example, the path function in Ramda:

const length = path(['innerThing', 'evenInnerer', 'superInnerer', 'length'], someObject);

This will produce a value of undefined if anything along that path is not present.

If you don't want to involve third-party libraries for this, it's quite trivial to write your own path function:

const path = (steps, obj) =>
    steps.reduce(
        (acc, next) => next in acc ? acc[next] : undefined,
        obj
    );

console.log(path(['a', 'b', 'c'], { a: { b: { c: 5 } } }));  // 5
console.log(path(['a', 'b', 'c'], { a: { b: { f: 5 } } }));  // undefined
JLRishe
  • 99,490
  • 19
  • 131
  • 169
1

Never use eval() in your code, I repeat never!

It's not a good practise to use eval() in your code, it's dangerous to use it. If a javascript code is injected using form inputs and you are storing that value in this variable then the browser will execute whatever the user has given as an input using eval.

Instead, use Optional Chaining in your code, like this:

someObject?.innerThing?.evenInnerer?.superInerer?.length

Above code will either return the length or undefined Optional chaining was introduced in ES2020. In this, you use ? before every . to ensure if the property exists on the references

Official documentation link: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining

Prathamesh Koshti
  • 1,322
  • 10
  • 17