Curried property accessor function that resolves deeply-nested object properties via dot/bracket-notation string path while mitigating TypeErrors via friendly and composable API.
npm install selectnTypeErrors via friendly and composable API.
    
``shell`
yarn add selectn
or
`shell`
npm install selectn --save
or
`html`
> You may also install selectn via [Bower] or [jspm].
###### allows you to refactor this:
person && person.info && person.info.name && person.info.name.full
###### into:
selectn('info.name.full', person)
###### or refactor this:
contacts.map(function (contact) {
return contact && contact.addresses && contact.addresses[0]
})
###### into:
contacts.map(selectn('addresses[0]')))

- Mitigate boilerplate guards like if (obj && obj.a && obj.a.b && obj.a.b.c).Cannot read property '...' of undefined
- Mitigate TypeError .'group[0].section.a.seat[3]'
- Multiple levels of array nesting: .'stats.temperature-today'
- Dashed key access: .selectn
- When the value at the given path is a function, it is invoked and the functions returned value is returned.
- is auto-curried so [partial application is automatic][Un-bind your JS with curry] when you omit the second argument.selectn
- uses Haskell style [parameter order] (AKA: data-last) which enables [pointfree style programming][Un-bind your JS with curry].selectn
- Functions returned by are higher-order property accessors which can be passed to other higher-order functions like [map] or [filter].
- Compatible with [modern and legacy browsers][browsers], Node/CommonJS, and AMD.
- No [eval][] or [Function][] (see: [eval][note] in disguise).
- No [typeof][] since, [typeof][] is not a real solution to this problem but can _appear_ to be due to the way the global scope is _implied_.
#### property accessor as predicate
> Avoid annoying __Cannot read property '...' of undefined__ TypeError without writing boilerplate anonymous functions or guards.
`js
var selectn = require('selectn')
var language = [
{ strings: { en: { name: 'english' } }},
{ strings: { es: { name: 'spanish' } }},
{ strings: { km: { name: 'khmer' } }},
{ strings: { es: { name: 'spanish' } }},
{ nodatas: {}}
]
var spanish = selectn('strings.es')
//=> [Function]
language.filter(spanish).length
//=> 2
`
#### point-free property accessor
> Access deeply nested properties (including dashed properties) using point-free style.
`js
var selectn = require('selectn')
var data = {
client: {
message: { 'message-id': 'd50afb80-a6be-11e2-9e96-0800200c9a66' }
}
}
var getId = selectn('client.message.message-id')
//=> [Function]
Promise.resolve(data).then(getId)
//=> 'd50afb80-a6be-11e2-9e96-0800200c9a66'
`
#### property accessor for functor
> Avoid wrapping property accessors in anonymous functions.
`js
var selectn = require('selectn')
var contacts = [
{ addresses: [ '123 Main St, Broomfield, CO 80020', '123 Main St, Denver, CO 80202' ] },
{ addresses: [ '123 Main St, Kirkland, IL 60146' ] },
{ phones: [] },
]
var primaryAddress = selectn('addresses[0]')
//=> [Function]
contacts.map(primaryAddress)
//=> [ '123 Main St, Broomfield, CO 80020', '123 Main St, Kirkland, IL 60146', undefined ]
`
#### support for keys containing .
> Pass an array as path instead of a string.
`js
var selectn = require('selectn')
var data = {
client: {
'message.id': 'd50afb80-a6be-11e2-9e96-0800200c9a66'
}
}
selectn(['client', 'message.id'], data)
//=> 'd50afb80-a6be-11e2-9e96-0800200c9a66'
`
#### value at path is a function
> Avoid var fn = data.may.be.a.fn; if (typeof fn === 'function') fn().
`js
var selectn = require('selectn')
function hi () { return 'hi' }
var data = { may: { be: { a: { fn: hi } } } }
selectn('may.be.a.fn', data)
//=> 'hi'
`
###### arguments
* path (String|Array) Dot/bracket-notation string path or array.
###### returns
- (Function) Unary function accepting the object to access.
###### arguments
* path (String|Array) Dot/bracket-notation string path or array.object (String|Array)
* Object to access.
###### returns
- (*|undefined) Value at path if path exists or undefined if path does not exist.
selectn has inspired ports to other languages:
|Language|Project|
|---|---|
|Python|selectn|
Other JS packages whose friendly API is driven by selectn:
- [array-groupby]
- [array.filter]
- [arraymap]
- [orderby-time]
- [regexp-id]
- [sum.js]
JS packages that have inspired selectn:
- [reach]
- [to-function]
Alternative packages you might like instead of selectn`:
- [_.get]
- [dref]
- [path-lookup]
- [pathval]
- [reach]
- [to-function]

[_.get]: https://www.npmjs.com/package/lodash.get
[Bower]: http://bower.io
[Duo]: http://duojs.org
[Function]: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function
[Property accessors]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_Accessors
[Sauce Test Status]: https://saucelabs.com/browser-matrix/selectn.svg
[Un-bind your JS with curry]: https://medium.com/@wilmoore/un-bind-your-js-with-curry-a8657a4138cb#.6dswguc2q
[array-groupby]: https://www.npmjs.com/package/array-groupby
[array.filter]: https://www.npmjs.com/package/array.filter
[arraymap]: https://www.npmjs.com/package/arraymap
[browsers]: https://saucelabs.com/u/selectn
[dref]: https://github.com/crcn/dref.js
[eval]: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/eval
[filter]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
[jspm]: http://jspm.io
[map]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
[note]: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Member_Operators#Note_on_eval
[orderby-time]: https://www.npmjs.com/package/orderby-time
[parameter order]: https://wiki.haskell.org/Parameter_order
[path-lookup]: https://github.com/yields/path-lookup
[pathval]: https://www.npmjs.com/package/pathval
[reach]: https://github.com/spumko/hoek#reachobj-chain
[regexp-id]: https://www.npmjs.com/package/regexp-id
[sum.js]: https://www.npmjs.com/package/sum.js
[to-function]: https://github.com/component/to-function
[typeof]: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/typeof