Skip to content

Instantly share code, notes, and snippets.

@Sleavely
Created October 7, 2019 13:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Sleavely/e0b130658a0ce87939baf1b9dcf92e6c to your computer and use it in GitHub Desktop.
Save Sleavely/e0b130658a0ce87939baf1b9dcf92e6c to your computer and use it in GitHub Desktop.
lodash.get alternative that covers _most_ cases.
// Graciously stolen from lodash's stringToPath
const charCodeOfDot = '.'.charCodeAt(0)
const reEscapeChar = /\\(\\)?/g
const rePropName = RegExp(
// Match anything that isn't a dot or bracket.
'[^.[\\]]+' + '|' +
// Or match property names within brackets.
'\\[(?:' +
// Match a non-string expression.
'([^"\'][^[]*)' + '|' +
// Or match strings (supports escaping characters).
'(["\'])((?:(?!\\2)[^\\\\]|\\\\.)*?)\\2' +
')\\]'+ '|' +
// Or match "" as the space between consecutive dots or empty brackets.
'(?=(?:\\.|\\[\\])(?:\\.|\\[\\]|$))'
, 'g')
/**
* Converts `string` to a property path array.
*
* @private
* @param {string} string The string to convert.
* @returns {Array} Returns the property path array.
*/
const stringToPath = (string) => {
const result = []
if (string.charCodeAt(0) === charCodeOfDot) {
result.push('')
}
string.replace(rePropName, (match, expression, quote, subString) => {
let key = match
if (quote) {
key = subString.replace(reEscapeChar, '$1')
}
else if (expression) {
key = expression.trim()
}
result.push(key)
})
return result
}
/**
* Recursively iterates over an object or array to find a nested path.
*
* @param {object|array} input
* @param {string} path A dot-notation path
* @returns {any|undefined} If a truthy value is found at the path, it is returned
*/
const get = (input, path) => {
const pathComponents = stringToPath(path)
const currentProp = pathComponents[0]
// end of the road?
if(pathComponents.length === 1) return input[currentProp]
// keep going
if(input[currentProp]) return get(input[currentProp], pathComponents.slice(1).join('.'))
// surrender to the endless void
return undefined
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment