2

I am trying to understand is how to create call methods after a method call.

For example in jquery you have something like this:

$("blah").data("data-id");

How would I make :

blah("cow").foo("moo");

Where the mothods blah and foo just console.log(value)?

K3NN3TH
  • 1,458
  • 2
  • 19
  • 31

4 Answers4

5

What you're referring to is a "fluent API" (also calling "chaining"). Your functions need to return the object that has the next method you want to call on it. For example,

var obj = function(){
        var self = this;
        self.blah = function(v){ console.log(v); return self; };
        self.foo = function(v){ console.log(v); return self; };
    };

    var o = new obj();
    o.blah("cow").foo("moo");

See this article for more info: http://www.i-programmer.info/programming/javascript/4676-chaining-fluent-interfaces-in-javascript.html

adam0101
  • 29,096
  • 21
  • 96
  • 174
  • Why rename this to self? – Nathan Wilson Aug 12 '15 at 14:17
  • @NathanWilson, it's just a safe way to write code. `this` refers to the object calling the method and can, therefore, change based on how the method is called. For example, if you were to assign the method to a click event without creating a closure, `this` would refer to the object raising the event. – adam0101 Aug 12 '15 at 16:00
  • @NathanWilson, Consider the following example: `var x = new function(){ this.prop = 1;this.get = function(){ return this.prop; }; }(); var y = {prop:2, getX: x.get}; console.log(y.getX());` When you run this, it returns *2* when you may be expecting *1*. Compare that to this: `var x = new function(){ var self = this; self.prop = 1; self.get = function(){ return self.prop; }; }(); var y = {prop:2, getX: x.get}; console.log(y.getX());` which retains a reference to the original object and returns *1* as expected. – adam0101 Aug 12 '15 at 16:01
  • @adam0101 ever heard of [`bind`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind)? – Thomas Ruiz Aug 12 '15 at 16:15
  • @ThomasRuiz, yes, I'm not saying there aren't other ways of doing it, but if I'm creating something that is going to be reused by another developer, I prefer to code in a way where they won't need to have explicit knowledge of how to implement it. And also, IE8 doesn't support `bind`. – adam0101 Aug 12 '15 at 16:54
  • @adam0101 browser compability for IE8 is useless now that windows XP support has been dropped by Microsoft. Besides, using `bind` inside your function won't require to use it afterwards. ES5 is now almost 6 years old, you know. – Thomas Ruiz Aug 12 '15 at 23:02
0

Return the object that contains the functions when the function is done. then you can chain them.

Here is an example from what I made a while back:

// I extend a class with a new function
HtmlObject.prototype.stop = function () {

    clearInterval( this.updater );
    this.animationQue   = [];
    this.updater        = undefined;

    // Then return the object that initially called the function
    return this;
};

So I could use it like object.stop().nextfuntion();

Also, In JQuery the $ is simply a shortcut to a JavaScript function.

I did the same in my test, but then with _. I must admit it is not as nifty as JQuery but:

var _ = function ( selector, context ) {
    var el = new xyvLib();
    // This will simply return a collection of HtmlObjects (of which you can find a snipet above)
    return el.fn.select( selector, context );
};
Xyv
  • 739
  • 7
  • 15
0

The function blah has to return an object with a method foo. Here is an example:

function blah(blahArg) {
    return {
       foo: function (fooArg) {
            console.log(blahArg, fooArg);
       }
    };
}

blah("cow").foo("moo");
0

You can call .foo on the result of blah() only when blah() returns an object which accepts the method foo on it.

A simple example would be like this:

function foo(value) {
    console.log(value);
}
function blah(value) {
    console.log(value);
    return { foo: foo } 
}
Robin James Kerrison
  • 1,727
  • 1
  • 15
  • 26