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();
);

4
  • 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. Commented Jun 14, 2021 at 20:53
  • I tried using this but it returns an error i may mis used it can you post an example please? Commented Jun 14, 2021 at 20:55
  • There's an example in the answers to the question I posted a link to. Commented Jun 14, 2021 at 20:56
  • Unfortunately this is a static function but mine can return either recall same function (foo) or call execute() Commented Jun 14, 2021 at 21:01

3 Answers 3

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)

Sign up to request clarification or add additional context in comments.

3 Comments

Certainly we have duplicates of "how to write a chainable function"?
@HereticMonkey - Find a better duplicate, and I'll be happy to close it with you.
That's what I need it's even more performant by evaluating all conditions together, thanks
2

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

}

test([]).foo({}).foo({}).execute();

Comments

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()
);

1 Comment

Good to know, @FZs! I will make a note of that in my post.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.