digory doo
digory doo

Reputation: 2311

Chaining member variables with side-effect with the chain not ending in a function

In the JavaScript chaijs testing library it is possible to chain members like this:

pm.expect (entry.NAME).to.be.a('string').that.is.not.empty;

This question is not about the testing library, but about the library's internal technique. I understand it works something like this: pm.expect is a function that returns an object that contains at least { to: { be: { a } } } where a is another function that returns at least { that: { is: { not: { empty } } } }.

The interesting thing is that empty apparently is not a function. If it was, I would have to call it like this: that.is.not.empty() (note the parentheses). So the chain ends with a member variable that is not a function.

How is it possible in JavaScript to consume that member variable to cause a side-effect? Can you show me a minimal JS snippet that allows me to end an expression with something that is not a function call (like empty;) and still act like it was a function call?

Upvotes: 2

Views: 63

Answers (2)

Tyler Roper
Tyler Roper

Reputation: 21672

Can you show me a minimal JS snippet that allows me to end an expression with something that is not a function call (like empty;) and still act like it was a function call?

Sure. One way is to use a getter:

const person = (name) => ({
  get greet()   { return `Hello ${name}!`;   },
  get dismiss() { return `Goodbye ${name}!`; }
});

console.log( person("Tyler").greet );
console.log( person("John").dismiss );

Upvotes: 3

Jonas Wilms
Jonas Wilms

Reputation: 138307

  function expect(value) {
      return {
         get empty() { return !value.length; },
      };
  }

 expect("test").empty // false
 expect("").empty // true

That's done with a getter, have a look at the ChaiJS sourcecode.

Upvotes: 3

Related Questions