Skip to content

Instantly share code, notes, and snippets.

@harish2704
Last active June 3, 2023 23:41
Show Gist options
  • Star 13 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save harish2704/d0ee530e6ee75bad6fd30c98e5ad9dab to your computer and use it in GitHub Desktop.
Save harish2704/d0ee530e6ee75bad6fd30c98e5ad9dab to your computer and use it in GitHub Desktop.
Simple lodash.get function in javascript
/* Implementation of lodash.get function */
function getProp( object, keys, defaultVal ){
keys = Array.isArray( keys )? keys : keys.split('.');
object = object[keys[0]];
if( object && keys.length>1 ){
return getProp( object, keys.slice(1) );
}
return object === undefined? defaultVal : object;
}
/* Implementation of lodash.set function */
function setProp( object, keys, val ){
keys = Array.isArray( keys )? keys : keys.split('.');
if( keys.length>1 ){
object[keys[0]] = object[keys[0]] || {};
return setProp( object[keys[0]], keys.slice(1), val );
}
object[keys[0]] = val;
}
@alexbruno
Copy link

alexbruno commented Oct 8, 2019

The above version doesn't support some formats supported by lodash.get.

Like: get(obj, ['forecast', 0, 'main.temp'], null)

But this version do it:

function get (object, path, value) {
  const pathArray = Array.isArray(path) ? path : path.split('.').filter(key => key)
  const pathArrayFlat = pathArray.flatMap(part => typeof part === 'string' ? part.split('.') : part)

  return pathArrayFlat.reduce((obj, key) => obj && obj[key], object) || value
}

@Sooro1024
Copy link

Sooro1024 commented Jan 22, 2020

The above version don't support some formats supported by lodash.get.

Like: get(obj, ['forecast', 0, 'main.temp'], null)

But this version do it:

function get (object, path, value) {
  const pathArray = Array.isArray(path) ? path : path.split('.').filter(key => key)
  const pathArrayFlat = pathArray.flatMap(part => typeof part === 'string' ? part.split('.') : part)

  return pathArrayFlat.reduce((obj, key) => obj && obj[key], object) || value
}

If return value is falsy it will not play properly.

function get (object, path, value) {
  const pathArray = Array.isArray(path) ? path : path.split('.').filter(key => key);
  const pathArrayFlat = pathArray.flatMap(part => typeof part === 'string' ? part.split('.') : part);
  const checkValue = pathArrayFlat.reduce((obj, key) => obj && obj[key], object);
  return  checkValue === undefined ? value : checkValue
}

@alexbruno
Copy link

Sorry @Sooro1024, but I don't think it's necessary!
Did you notice the || in my return?

return pathArrayFlat.reduce((obj, key) => obj && obj[key], object) || value

If the reduce result is falsy (undefined inclusive), the value is returned.

So, if the expected return is a number, just pass a value = 0. And if a boolean is expected, just pass a value = false.

So, I think extra code is not necessary. Just take some Node or DevTools console test:

js

And here is a use test:

get

@Sooro1024
Copy link

Sooro1024 commented Jan 28, 2020 via email

@souljorje
Copy link

souljorje commented Nov 23, 2021

@pi0, you solution throws an error, but thanks for inspiration for the most performant solution from provided here.

const getPropByPath = (object, path, defaultValue) => {
    const _path = Array.isArray(path)
        ? path
        : path.split('.');
    if (object && _path.length) return getPropByPath(object[_path.shift()], _path, defaultValue);
    return object === undefined ? defaultValue : object;
};

// without default value
const getPropByPath = (object, path) => {
    const _path = Array.isArray(path)
        ? path
        : path.split('.');
    if (object && _path.length) return getPropByPath(object[_path.shift()], _path);
    return object;
};

Benchmarks: https://jsbench.me/ogkwc7fxlg/1. I didn't include implementations out of scope of original lodash.get and those which iterate over whole path without break - i.e. reduce-based - they're too slow.

@specimen151
Copy link

@pi0, you solution throws an error, but thanks for inspiration for the most performant solution from provided here.

const getPropByPath = (object, path, defaultValue) => {
    const _path = Array.isArray(path)
        ? path
        : path.split('.');
    if (object && _path.length) return getPropByPath(object[_path.shift()], _path, defaultValue);
    return object === undefined ? defaultValue : object;
};

// without default value
const getPropByPath = (object, path) => {
    const _path = Array.isArray(path)
        ? path
        : path.split('.');
    if (object && _path.length) return getPropByPath(object[_path.shift()], _path);
    return object;
};

Benchmarks: https://jsbench.me/ogkwc7fxlg/1. I didn't include implementations out of scope of original lodash.get and those which iterate over whole path without break - i.e. reduce-based - they're too slow.

This solution fixed for me a problem: Empty string counts as undefined.
I'd like the empty string back. It's not the same (for me).

I'm talking about the version without default value.

@romanown
Copy link

setProp is not work.

@andrewchilds
Copy link

I created a fork of this version that includes tests, handles falsey values (including undefined), and handles objects-inside-arrays (i.e. '[0].id') as well as arrays-inside-objects (i.e. 'a.b[0].c'):

https://gist.github.com/andrewchilds/30a7fb18981d413260c7a36428ed13da

@romanown
Copy link

many thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment