Last week, we looked at return values in JavaScript functions. This week, let's look at how we can use that knowledge to chain calls to different functions.

Let's revisit the toTitleCase() helper function we looked at last month:

/**
* Convert a string to title case
* {@link https://gist.github.com/kieranbarker/293b74f1b3b46272315d2e1719786b03}
* @param {String} str The string to convert
* @returns {String} The converted string
*/

function toTitleCase(str) {
return str.toLowerCase().split(' ').map(function(word) {
return word.charAt(0).toUpperCase() + word.slice(1);
}).join(' ');
}

Ignoring the arguments, our function chain looks like this:

str.toLowerCase().split().map().join();

The reason this works is because the return value from each function call has access to the next function in the chain. Let's break this down a bit more.

toLowerCase()

We start with our string, str. Every string has access to the toLowerCase() method through its prototype chain, which is why we're able to call it.

If we call toTitleCase('sTrAwBeRrY sHoRtCaKe'), our chain starts like this:

str               // 'sTrAwBeRrY sHoRtCaKe'
.toLowerCase(); // 'strawberry shortcake'

The toLowerCase() method returns a new string.

split()

Because the toLowerCase() method returns a new string, we have access to the split() method. Like the toLowerCase() method, the split() method is available to all strings via their prototype chain.

Now our chain looks like this:

str              // 'sTrAwBeRrY sHoRtCaKe'
.toLowerCase() // 'strawberry shortcake'
.split(); // ['strawberry', 'shortcake']

The split() method returns a new array.

map()

Because the split() method returns a new array, we have access to the map() method. The map() method is available to all arrays via their prototype chain.

At this point, our chain is as follows:

str              // 'sTrAwBeRrY sHoRtCaKe'
.toLowerCase() // 'strawberry shortcake'
.split() // ['strawberry', 'shortcake']
.map(); // [Strawberry', 'Shortcake']

The map() method returns a new array.

join()

Because the map() method returns a new array, we have access to the join() method. Like the map() method, the join() method is available to all arrays via their prototype chain.

Finally, our chain ends like this:

str              // 'sTrAwBeRrY sHoRtCaKe'
.toLowerCase() // 'strawberry shortcake'
.split() // ['strawberry', 'shortcake']
.map() // [Strawberry', 'Shortcake']
.join(); // 'Strawberry Shortcake'

The join() method returns a new string. We could chain another string method if we wanted, but we don't need to since we've arrived at the desired value. Instead, we make our final string—'Strawberry Shortcake'—our function's return value.

Further chaining

Since our toTitleCase() function returns a new string, it means we can chain any string method onto its return value.

For example, we can convert a string from lower case to title case and back again. Although this is a pointless operation, it does help illustrate the point:

toTitleCase('chocolate milkshake').toLowerCase(); // 'chocolate milkshake'

Again, the reason this works is because our toTitleCase() function returns a new string, and all strings have access to the toLowerCase() method through their prototype chain.

This shit can be confusing, but here's some recommended reading:

I hope this post has been helpful, but I'd also love to know if not! If you have any feedback, feel free to shoot me an email. 😌