Back in the days when the Web was all made of jQuery, we were constantly using a pattern - function (or method) chaining. It looks like that:
$("#p1")
.css("color", "red")
.slideUp(2000)
.slideDown(2000);
The first line ($("#p1")
) selects a DOM element. The rest is changing the color and animating it.
We should consider method chaining when we have a lot of small functions, and they have to be executed on a single object.
Let's see how the implementation of this pattern looks like. We will define a shopping cart factory function:
function ShoppingCart() {
const products = [];
function add(product, price) {
products.push({ product, price });
}
function total() {
return products.reduce((res, product) => (res += product.price), 0);
}
return { add, total }
}
We may create a shopping cart, add products and get the total price at the end.
const cart = ShoppingCart();
cart.add("t-shirt", 50)
cart.add("backpack", 120)
cart.add("socks", 7)
console.log(cart.total()); // 177
Now let's make the add
method chainable. To do that, we have to return an object with this add
method. This is so we can call it again.
function ShoppingCart() {
const products = [];
const api = { add, total };
function add(product, price) {
products.push({ product, price });
return api;
}
function total() {
return products.reduce((res, product) => (res += product.price), 0);
}
return api;
}
Now we can rewrite our example as:
const cart = ShoppingCart();
const total = cart
.add("t-shirt", 50)
.add("backpack", 120)
.add("socks", 7)
.total();
console.log(total); // 177
Notice that total
is not the same as add
because it doesn't return the same api
object.