0

I have the following function I want to make sure that I can execute foo function multiple times before executing final execute function:

let test = (object) => {
  return {
    foo: (condition) => {
      return {
        execute: () => {
          return object.filter(obj => condition(obj))
        },
        foo: // Call same function
      }
    },
  }

}

console.log(
  test(object).foo(condition1).foo(condition2).execute();
);
Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
touati ahmed
  • 311
  • 8
  • 21
  • You'll find that "chainable" functions generally return the object with the function that's being run. So you'd have an object that has `foo` and `execute` and `foo` would return `this` so that `foo` or `execute` could be run on the result. – Heretic Monkey Jun 14 '21 at 20:53
  • I tried using this but it returns an error i may mis used it can you post an example please? – touati ahmed Jun 14 '21 at 20:55
  • There's an example in the answers to the question I posted a link to. – Heretic Monkey Jun 14 '21 at 20:56
  • Unfortunately this is a static function but mine can return either recall same function (foo) or call execute() – touati ahmed Jun 14 '21 at 21:01

3 Answers3

2

let test = (object) => {
  return {
    foo: function f(condition) {
      return {
        execute: () => {
          return object.filter(obj => condition(obj))
        },
        foo: f
      }
    },
  }

}

test([]).foo({}).foo({}).execute();
Lrazerz
  • 164
  • 6
2

Assign the object to a const before returning it, and use the reference to the const when executing foo:

const test = (arr) => {
  const conditions = []
  
  const o = {
    foo: (condition) => {
      conditions.push(condition)
    
      return {
        execute: () => {
          return arr.filter(obj => conditions.every(c => c(obj))) // or some passing a single condition is enough
        },
        foo: o.foo
      }
    },
  }

  return o
}

const result = test([{ a: 1 }, { a: 4 }, { a: 6 }])
  .foo(({ a }) => a % 2 === 0)
  .foo(({ a }) => a % 3 === 0)
  .execute()

console.log(result)
Ori Drori
  • 183,571
  • 29
  • 224
  • 209
2
Note: The old answer here said to use arguments.callee, but it is deprecated and this solution works just as well.

Use a non-arrow function and use this.foo to acess the object being returned:

const test = (object) => ({
  foo(condition) {
    return {
      execute() {
        return object.filter(condition);
      },
      foo: this.foo,
    };
  },
});

// lets test it!
const object = ["a", "b", "c", "d", "e", "f", "g"];
const condition1 = () => true;
const condition2 = () => Math.random() > 0.5;

console.log(
  test(object).foo(condition1).foo(condition2).execute()
);