Chaining - Fluent Interfaces In JavaScript
Written by Ian Elliot   
Monday, 20 August 2012
Article Index
Chaining - Fluent Interfaces In JavaScript
Getting Complicated

Getting complicated

 Once again this is all there is to chaining - just making sure you return the correct object for the next function to have the correct conext.

If you want to be sophisticated then you don't always have to return the same object and, as already mentioned, this would be appropriate for a search method say that returned different types of object.

One problem with chained function calls is what do you do about the result of a function? After all, you can't return it because to support chaining you have to return a suitable object. The answer is that the object you return has to be both the context for the next function call and incorporate the result of the function.

That is, if you want to implement an API in a fluent style then you have to create an object which not only hosts the methods you want to chain but which stores what would have been the results of these operations as its internal state.

Let's take a look at some examples.

Initialization

One common use of function chaining is to create a fluent interface to initialize an object, You can initialize everything using the constructor but this often results in a constructor that is very difficult to use. Providing set functions that can be chained produces a neater and more flexible initialization API.

For example, suppose you have an address object which holds a person's details, then you could define the constructor as:

var AddressConstruct = function () {
            this.name;
            this.number;
            this.age;

            this.setName = function (name) {
                this.name = name;
                return this;
            };
            this.setNumber = function (number){
                this.number = number;
                return this;
            };
            this.setAge = function (age) {
                this.age = age;
                return this;
            }
        };

 

Following this definition you can write things like:

var add = new AddressConstruct();
add.setAge(24).setName("Ian").setNumber(1);

Once you have seen the basic method you can see that it i possible to extend the idea to including methods to modify values that have already been set. For example you could have an addAge method which increments the age field and so on.

A DSL For Calculation

As an example of how function chaining can become a DSL (Domain Specific Language), consider the task of implementing a calculator or math API. JavaScript already has the Math object, which provides many standard functions, but this is an example of how it could have been done.

The first problem we have to solve is that, unlike a non-fluent approach to calculation, our functions cannot return the result of the calculation. In fact, the result has to be stored as the state of the calc object. This is another common pattern in using function chaining - what used to be a result often has to be built into the object's state.

The constructor is:

var CalcConstruct = function () {
      this.value = 0;
      this.square = function () {
       this.value = Math.pow(this.value, 2);
       return this;
      };
      this.sqrt = function () {
       this.value = Math.sqrt(this.value);
       return this;
      };
      this.display = function () {
       alert(this.value);
       return this;
      };
      this.setValue = function (value) {
       this.value = value;
       return this;
      };
      this.times = function (times) {
       this.value = this.value * times;
       return this;
      };
    };

 

Notice that all of the functions work with this.value and return this. The range of operations is quite small - square, sqrt, times, setValue and display. Even so, you can now write calculations that look fairly impressive - for example:

var c = new CalcConstruct();
    c.setValue(100)
     .sqrt()
     .display()
     .square()
     .display()
     .times(3)
     .display();

 

You can see that it does start to look like a program in a special language.

Where Next

This final example is a little more realistic, but it hardly starts to dig into the sophistication you can invent - and JavaScript is ideal for this sort of elaboration. For example, if you make the internal state of the object a collection, you can introduce functions which select and even enumerate on the collection. You can arrange for functions to return different types of object to implement conditionals and so on. You can also pass functions within methods to determine what happens. For example:

c.apply(sin),reduce(sum);

could be implemented to apply the sin function to each member of the collection and then perform a reduction on the collection using the sum function i.e. form a total of the values in the collection.

If you want to see more examples of using the fluent style then see jQuery or LINQ both of which take function chaining as key design principles.

 

blog comments powered by Disqus

 

Banner


Just JavaScript - In The Beginning Was The Object

JavaScript is a very subtle and sophisticated language and it deserves to be treated in its own right and not as a poor copy of other object-oriented language. In this first chapter of Just JavaScript [ ... ]



Javascript Jems - Lambda expressions

JavaScript has lambda expressions in all but name. Find out how they work and how to use them.


Other Articles

 

To be informed about new articles on I Programmer, install the I Programmer Toolbar, subscribe to the RSS feed, follow us on, Twitter, Facebook, Google+ or Linkedin,  or sign up for our weekly newsletter.

 



Last Updated ( Monday, 20 August 2012 )
 
 

   
RSS feed of all content
I Programmer - full contents
Copyright © 2014 i-programmer.info. All Rights Reserved.
Joomla! is Free Software released under the GNU/GPL License.