Emulate Java 8 predicate chaining in JavaScript
I believe you could retain the same level of flexibility without managing extra objects by using higher order functions. This also has the advantage of treating the predicates as functions and nothing more.


const records = [
  { name: 'Andrew' , age: 21, position: 'Developer' },
  { name: 'Bill'   , age: 26, position: 'Developer' },
  { name: 'Chris'  , age: 45, position: 'Manager'   },
  { name: 'Dave'   , age: 30, position: 'Developer' },
  { name: 'Eric'   , age: 32, position: 'Manager'   }
];

const display = ({ name, age, position }) =&gt;
     `${name} (${age}) [${position}]`;

const not = condition =&gt; (...args) =&gt; !condition(...args);

const and = (...conditions) =&gt; (...args) =&gt;
    conditions.reduce(
        (a,b)=&gt;a&amp;&amp;b(...args),true
    )

const or = (...conditions) =&gt; (...args) =&gt;
    conditions.reduce(
        (a,b)=&gt;a||b(...args),false
    )

const ageOver21 = ({age}) =&gt; age &gt; 21
const isDeveloper = ({position}) =&gt; position === 'Developer';
const ageOver21AndIsDeveloper = and(ageOver21,isDeveloper);

console.log(records.filter(ageOver21AndIsDeveloper).map(display).join(', '));

const billOrManager = or(
    ({name}) =&gt; name === 'Bill',
    ({position}) =&gt; position === 'Manager'
)

console.log(records.filter(billOrManager).map(display).join(', '));

const notUnder30 = not(({ age }) =&gt; age &lt; 30)

console.log(records.filter(notUnder30).map(display).join(', '));

console.log(
    records.filter(
        or(billOrManager,ageOver21AndIsDeveloper)
    )
    .map(display).join(', ')
);