foop
Version:
interfaces that describe their intentions.
74 lines (71 loc) • 2.32 kB
JavaScript
// const forOwn = require('../loop/each/forOwn')
const hasOwnProperty = require('../util/hasOwnProperty')
const isObj = require('../is/obj')
const curry = require('./curry')
/**
* Takes a spec object and a test object returns true if the test satisfies
* the spec. Each of the spec's own properties must be a predicate function.
* Each predicate is applied to the value of the corresponding property of the
* test object. `where` returns true if all the predicates return true, false
* otherwise.
*
* `where` is well suited to declaratively expressing constraints for other
* functions such as [`filter`](#filter) and [`find`](#find).
*
* @since 5.0.0-beta.6
* @memberOf fp
* @curried 2
*
* @param {Object} spec
* @param {Object} testObj
* @return {Boolean}
*
* @tests fp/where
*
* {@link https://github.com/jashkenas/underscore/blob/master/underscore.js#L323 underscore-where}
* {@link https://github.com/lodash/lodash/blob/master/.internal/baseConformsTo.js lodash-conformsto}
* {@link https://github.com/ramda/ramda/blob/v0.24.1/src/where.js ramda-where}
* @see {@link underscore-where}
* @see {@link ramda-where}
* @see {@link lodash-conformsto}
*
* @func
* @fork v0.1.1
* @category Object
* @sig {String: (* -> Boolean)} -> {String: *} -> Boolean
*
* @example
*
* // pred :: Object -> Boolean
* var pred = where({
* a: equals('foo'),
* b: not(equals('bar')),
* x: gt('_', 10),
* y: lt('_', 20)
* })
*
* pred({a: 'foo', b: 'xxx', x: 11, y: 19}) //=> true
* pred({a: 'xxx', b: 'xxx', x: 11, y: 19}) //=> false
* pred({a: 'foo', b: 'bar', x: 11, y: 19}) //=> false
* pred({a: 'foo', b: 'xxx', x: 10, y: 19}) //=> false
* pred({a: 'foo', b: 'xxx', x: 11, y: 20}) //=> false
*
*/
module.exports = curry(2, function where(spec, testObj) {
// forOwn(spec, (test, prop) => {
// hasOwnProperty(testObj, prop) && !spec[prop](testObj[prop])
// })
for (let prop in spec) {
if (hasOwnProperty(spec, prop)) {
if (isObj(spec[prop]) && hasOwnProperty(testObj, prop)) {
if (!where(spec[prop], testObj[prop])) {
return false
}
}
else if (!hasOwnProperty(testObj, prop) || !spec[prop](testObj[prop])) {
return false
}
}
}
return true
})