Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make function chainable without executing? like `obj.fn.fn` instead of `obj.fn().fn()`

I have two functions in an object

var obj = {};
obj.fn1 = function(){ console.log('obj.fn1'); return this; };
obj.fn2 = function(){ console.log('obj.fn2'); return this; };

I want to be able to do

obj.fn1.fn2()
obj.fn2.fn1()

How to do this?

EDIT: fn1 and fn2 could be functions or property accessors, I don't care as long as they do stuff.

I've seen it in many libraries, like chalk color.red.bold('string').

like image 684
laggingreflex Avatar asked Nov 10 '22 14:11

laggingreflex


1 Answers

You can do it if fn1, fn2 and obj have references to both functions. Object.assign (ES6) helps here:

var base = {
  fn1: function fn1() { console.log('fn1'); return this; },
  fn2: function fn2() { console.log('fn2'); return this; }
}

Object.assign(base.fn1, base);
Object.assign(base.fn2, base);
var obj = Object.assign({}, base);

obj.fn1();
obj.fn1.fn2();
obj.fn2();
obj.fn1.fn2.fn1.fn1();

babel.js repl

I expect this is how your library example works.

If Object.assign is not available you could use a polyfill or common alternative like _.assign from lodash.

like image 175
joews Avatar answered Nov 14 '22 21:11

joews