Home > OS >  Uncertain behaviour of _.get
Uncertain behaviour of _.get

Time:03-29

let a = {
   b  : null
}

_.get(a, 'b',''); //return null

but

_.get (a, null, '') //return ''

Is null a falsy value for _.get()?

let a = {
   b  : {c:{
}
} //basically a nested object

I'm trying to do _.get(a, 'b.c','').toString() and I'm getting error because _.get return null. What is the best readable way to write this?

CodePudding user response:

The third argument defaultValue will only be returned for undefined resolved values, not null. see docs

If you want a fallback value for null or undefined, use the nullish coalescing operator:

(_.get(a, "b.c") ?? "").toString()

Below are different results using different mechanisms in defining default value:

let a;

a = { b: null };
_.get(a, "b", ""); // null
_.get(a, "b") ?? ""; // ""
_.get(a, "b") || ""; // ""

a = { };
_.get(a, "b", ""); // ""

a = { b: undefined };
_.get(a, "b", ""); // ""

a = { b: 0 };
_.get(a, "b") || ""; // ""
_.get(a, "b") ?? ""; // 0

CodePudding user response:

In

_.get(a, 'b','');

you ask for the property a['b'], which happens to be null, which isn't undefined, so you get null as the final result. Next, in

_.get(a, null, '');

you ask for the property a['null'], which doesn't exist, so it's undefined, and you end up with the fallback value ''. Finally, with

let a = {b: {c: {}}};
_.get(a, 'b.c', '');

you seem to be asking for a['b']['c'], which would be an empty object. However, the dotted path notation is Lodash-specific. If you are using Underscore, the path is interpreted as a['b.c'] by default, which doesn't exist and is undefined. In that case, you should get '' as the final result. I see no way this expression could result in null, even if you are using the original value of a = {b: null}.

If you are, in fact, using Underscore and you want to retrieve the nested c object within the b property, you have two options. Firstly, you can use array path notation, which is portable between Underscore and Lodash:

_.get(a, ['b', 'c'], '');

Secondly, you can override _.toPath to enable dotted path notation for all Underscore functions:

const originalToPath = _.toPath;
_.toPath = function(path) {
    if (_.isString(path)) return path.split('.');
    return originalToPath(path);
}

_.get(a, 'b.c', '');

I wouldn't recommend this, because it can break code that is trying to retrieve properties that contain the period character . in the name. I mention it for completeness; use your own judgment.

  • Related