search
HomeWeb Front-endJS TutorialFunction Composition: Building Blocks for Maintainable Code

Function Composition: Building Blocks for Maintainable Code

JavaScript function combination: build more maintainable code

JavaScript Function Composition is a technique of combining multiple simple functions into a single more complex function that performs subfunction operations on a given data in logical order. The order in which functions are applied produces different results.

To write maintainable code, it is crucial to understand the return type of each combined function to ensure that the next function can handle it correctly. JavaScript does not prevent the combination from returning functions of inappropriate types, so this part of the responsibility falls on the programmer.

For those who are not familiar with the functional programming paradigm, combining functions can make the code seem complicated. However, with the advent of ES2015 syntax, using arrow functions, it is possible to create simple combination functions in one line of code without the need for special combination methods.

Combined functions should be pure functions, which means that each time a specific value is passed to a function, the function should return the same result, and the function should not have side effects of changing its own external values. This will produce cleaner, more readable code.

This article was reviewed by Jeff Mott, Dan Prince and Sebastian Seitz. Thanks to all SitePoint peer reviewers for getting SitePoint content to its best!

Function Composition: Building Blocks for Maintainable Code

One of the advantages of functional thinking is the ability to build complex functions using small, easy-to-understand single functions. But sometimes this requires thinking about the problem in reverse, not positively, in order to figure out how to create the most elegant solution. In this article, I will take a step-by-step approach to checking the combination of functions in JavaScript and demonstrate how it produces code that is easier to understand and has fewer errors.

Nested functions

Composition is a technique that allows you to combine two or more simple functions into a more complex function that executes each subfunction on any data passed in logical order. To get this result, you need to nest one function in another and repeat the operations of the external function on the result of the inner function until the result is produced. And the results may vary depending on the order in which the function is applied. This can be easily demonstrated using programming techniques we already know in JavaScript by passing a function call as a parameter to another function:

function addOne(x) {
  return x + 1;
}
function timesTwo(x) {
  return x * 2;
}
console.log(addOne(timesTwo(3))); //7
console.log(timesTwo(addOne(3))); //8

In this case, we define an addOne() function to add 1 to a value, and a timesTwo() function to multiply a value by 2. By passing the results of one function as an argument to another, we can see how nesting one of them in the other produces different results, even if the initial values ​​are the same. The inner function is executed first, and the result is passed to the outer function.

Imperative combination

If you want to repeat the same sequence of operations, it may be convenient to define a new function to automatically apply the first and second function. This might look like this:

function addOne(x) {
  return x + 1;
}
function timesTwo(x) {
  return x * 2;
}
console.log(addOne(timesTwo(3))); //7
console.log(timesTwo(addOne(3))); //8

In this case, we manually combine the two functions together in a specific order. We create a new function that first assigns the passed value to the holder variable, then updates the value of that variable by executing the first function, followed by the second function, and finally returns the value of that holder. (Note that we use a variable called holder to temporarily hold the value we passed in. For such a simple function, the extra local variables seem redundant, but even in imperative JavaScript, the arguments to the function will be passed in It is also a good habit to treat values ​​as constants. It is possible to modify them locally, but this creates confusion about what the parameter values ​​are when called at different stages of a function.) Similarly, if we want to create another new function to the contrary The order of applying these two smaller functions, we can do the following:

// ...来自上面的先前函数定义
function addOneTimesTwo(x) {
  var holder = x;
  holder = addOne(holder);
  holder = timesTwo(holder);
  return holder;
}
console.log(addOneTimesTwo(3)); //8
console.log(addOneTimesTwo(4)); //10

Of course, this code starts to look very repetitive. Our two new combined functions are almost identical, except that the two smaller functions they call have different execution orders. We need to simplify it (like not repeating ourselves). Also, using temporary variables that change their value like this is not very functional, even if it is hidden inside the combinatorial function we are creating. Bottom line: We can do better.

Create functional combinations

Let's create a combinatorial function that takes existing functions and combines them together in the order we want. In order to do this in a consistent way without having to deal with internal details every time, we have to decide the order in which we want to pass the functions as parameters. We have two options. The parameters will be functions, respectively, which can be executed from left to right or from right to left. That is, using the new function we proposed, compose(timesTwo, addOne) can represent timesTwo(addOne()) to read parameters from right to left, or addOne(timesTwo()) to read parameters from left to right. The advantage of executing parameters from left to right is that they will be read in the same way in English, which is very similar to how we named the combined function timesTwoAddOne() to imply that multiplication should happen before addition. We all know the importance of logical naming for concise and easy-to-read code. The disadvantage of executing parameters from left to right is that the value to be operated must be placed in front. However, putting the value in front makes it less convenient to combine the resultant functions with other functions in the future. To explain the thought behind this logic well, you can’t go beyond Brian Lonsdorf’s classic video Hey Underscore, You’re Doing it Wrong. (Although it should be noted that now Underscore has an FP option that can help solve the functional programming problem that Brian discusses when using Underscore with functional programming libraries such as lodash-fp or Ramda.) Anyway, we really want to What you want to do is first pass in all configuration data, and then finally pass in the value you want to operate on. Therefore, it is most logical to define our combined functions as reading their parameters and applying them from right to left. So we can create a basic combination function that looks like this:

function addOne(x) {
  return x + 1;
}
function timesTwo(x) {
  return x * 2;
}
console.log(addOne(timesTwo(3))); //7
console.log(timesTwo(addOne(3))); //8

Using this very simple combination function, we can build our two previous complex functions more simply and see the same result:

// ...来自上面的先前函数定义
function addOneTimesTwo(x) {
  var holder = x;
  holder = addOne(holder);
  holder = timesTwo(holder);
  return holder;
}
console.log(addOneTimesTwo(3)); //8
console.log(addOneTimesTwo(4)); //10

While this simple combinatorial function works, it does not consider many issues that limit its flexibility and applicability. For example, we might want to combine more than two functions. Furthermore, we lose this information in the process. We can solve these problems, but it is not necessary to master how the combination works. Rather than writing it yourself, inheriting a more powerful combination from existing functional libraries such as Ramda, by default it does take into account the right-to-left order of parameters.

Type is your responsibility

It is important to remember that it is the responsibility of the programmer to know the return type of each combined function so that the next function can handle it correctly. Unlike pure functional programming languages ​​that perform strict type checking, JavaScript does not prevent you from trying to combine functions that return values ​​of inappropriate types. You are not limited to passing numbers, but not even to keeping the same variable type from one function to the next. But you are responsible for making sure that the function you are combining is ready to process any value returned by the previous function.

Consider your audience

Always remember that others may need to use or modify your code in the future. Using combinations in traditional JavaScript code can be complicated for those who are not familiar with the functional programming paradigm. The goal is to be simpler, easier to read and maintain code. However, with the advent of ES2015 syntax, it is even possible to create simple combination functions as single-line calls using arrow functions without the need for special combination methods:

function addOne(x) {
  return x + 1;
}
function timesTwo(x) {
  return x * 2;
}
console.log(addOne(timesTwo(3))); //7
console.log(timesTwo(addOne(3))); //8

Let's start combining today

As with all functional programming techniques, it is important to remember that your combined functions should be pure functions. In short, this means that every time a specific value is passed to a function, the function should return the same result, and the function should not have the side effects of changing its own external values. Combination nesting is very convenient when you have a set of related functions you want to apply to your data, and you can break the components of that function into reusable and easy to combine functions. As with all functional programming techniques, I recommend adding the combination to your existing code with caution to familiarize yourself with it. If you do it right, the result will be cleaner, drier, and easier to read code. Isn't this what we all want?

(The following is FAQ, which has been adjusted and streamlined according to the original text, and duplicate information is avoided)

Frequently Asked Questions about Function Combination and Maintainable Code

  • What is a combination of functions in programming? Function combination is the concept of combining simple functions into more complex functions. You can create complex and powerful functions with these small reusable functions just like building blocks. This helps make the code more readable, easier to maintain, and more scalable.

  • How does function combination promote maintainable code? Function combinations promote maintainability by encouraging the use of small, reusable functions. These functions are easier to understand, test, and debug. When these small functions are combined to create more complex functions, it is easier to pinpoint and fix any issues that may arise. This modular approach also makes it easier to update or modify certain parts of the code without affecting the entire system.

  • What are the best practices for writing maintainable code? Writing maintainable code involves a number of best practices, including: keeping functions small and focusing on a single task; using meaningful variables and function names; annotating code to explain the “why” behind the code logic; following Consistent coding style and structure.

  • What is the relationship between function combination and functional programming? Function combination is a basic concept in functional programming. Functional programming is an example of treating calculations as evaluation of mathematical functions and avoiding changing states and variable data. In this paradigm, function combinations play a crucial role in building more complex functions from simpler functions, thereby improving the reusability and maintainability of the code.

  • What are the challenges of implementing function combinations? Function combinations have many benefits, but they can also bring challenges. One challenge is that if not managed properly, it can lead to hard to read code, especially when combining multiple functions. Handling errors and exceptions in a chain of combined functions can also be difficult. However, these challenges can be mitigated by good coding practices and correct use of function combinations.

  • How to improve code testing with function combinations? Function combinations can make code testing easier and more efficient. Since a combined function is composed of smaller, independent functions, you can test each small function separately. This makes it easier to isolate and fix bugs. It also facilitates the practice of unit testing, where each part of the software is tested individually to ensure it works properly.

The above is the detailed content of Function Composition: Building Blocks for Maintainable Code. For more information, please follow other related articles on the PHP Chinese website!

Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
C   and JavaScript: The Connection ExplainedC and JavaScript: The Connection ExplainedApr 23, 2025 am 12:07 AM

C and JavaScript achieve interoperability through WebAssembly. 1) C code is compiled into WebAssembly module and introduced into JavaScript environment to enhance computing power. 2) In game development, C handles physics engines and graphics rendering, and JavaScript is responsible for game logic and user interface.

From Websites to Apps: The Diverse Applications of JavaScriptFrom Websites to Apps: The Diverse Applications of JavaScriptApr 22, 2025 am 12:02 AM

JavaScript is widely used in websites, mobile applications, desktop applications and server-side programming. 1) In website development, JavaScript operates DOM together with HTML and CSS to achieve dynamic effects and supports frameworks such as jQuery and React. 2) Through ReactNative and Ionic, JavaScript is used to develop cross-platform mobile applications. 3) The Electron framework enables JavaScript to build desktop applications. 4) Node.js allows JavaScript to run on the server side and supports high concurrent requests.

Python vs. JavaScript: Use Cases and Applications ComparedPython vs. JavaScript: Use Cases and Applications ComparedApr 21, 2025 am 12:01 AM

Python is more suitable for data science and automation, while JavaScript is more suitable for front-end and full-stack development. 1. Python performs well in data science and machine learning, using libraries such as NumPy and Pandas for data processing and modeling. 2. Python is concise and efficient in automation and scripting. 3. JavaScript is indispensable in front-end development and is used to build dynamic web pages and single-page applications. 4. JavaScript plays a role in back-end development through Node.js and supports full-stack development.

The Role of C/C   in JavaScript Interpreters and CompilersThe Role of C/C in JavaScript Interpreters and CompilersApr 20, 2025 am 12:01 AM

C and C play a vital role in the JavaScript engine, mainly used to implement interpreters and JIT compilers. 1) C is used to parse JavaScript source code and generate an abstract syntax tree. 2) C is responsible for generating and executing bytecode. 3) C implements the JIT compiler, optimizes and compiles hot-spot code at runtime, and significantly improves the execution efficiency of JavaScript.

JavaScript in Action: Real-World Examples and ProjectsJavaScript in Action: Real-World Examples and ProjectsApr 19, 2025 am 12:13 AM

JavaScript's application in the real world includes front-end and back-end development. 1) Display front-end applications by building a TODO list application, involving DOM operations and event processing. 2) Build RESTfulAPI through Node.js and Express to demonstrate back-end applications.

JavaScript and the Web: Core Functionality and Use CasesJavaScript and the Web: Core Functionality and Use CasesApr 18, 2025 am 12:19 AM

The main uses of JavaScript in web development include client interaction, form verification and asynchronous communication. 1) Dynamic content update and user interaction through DOM operations; 2) Client verification is carried out before the user submits data to improve the user experience; 3) Refreshless communication with the server is achieved through AJAX technology.

Understanding the JavaScript Engine: Implementation DetailsUnderstanding the JavaScript Engine: Implementation DetailsApr 17, 2025 am 12:05 AM

Understanding how JavaScript engine works internally is important to developers because it helps write more efficient code and understand performance bottlenecks and optimization strategies. 1) The engine's workflow includes three stages: parsing, compiling and execution; 2) During the execution process, the engine will perform dynamic optimization, such as inline cache and hidden classes; 3) Best practices include avoiding global variables, optimizing loops, using const and lets, and avoiding excessive use of closures.

Python vs. JavaScript: The Learning Curve and Ease of UsePython vs. JavaScript: The Learning Curve and Ease of UseApr 16, 2025 am 12:12 AM

Python is more suitable for beginners, with a smooth learning curve and concise syntax; JavaScript is suitable for front-end development, with a steep learning curve and flexible syntax. 1. Python syntax is intuitive and suitable for data science and back-end development. 2. JavaScript is flexible and widely used in front-end and server-side programming.

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

DVWA

DVWA

Damn Vulnerable Web App (DVWA) is a PHP/MySQL web application that is very vulnerable. Its main goals are to be an aid for security professionals to test their skills and tools in a legal environment, to help web developers better understand the process of securing web applications, and to help teachers/students teach/learn in a classroom environment Web application security. The goal of DVWA is to practice some of the most common web vulnerabilities through a simple and straightforward interface, with varying degrees of difficulty. Please note that this software

MantisBT

MantisBT

Mantis is an easy-to-deploy web-based defect tracking tool designed to aid in product defect tracking. It requires PHP, MySQL and a web server. Check out our demo and hosting services.

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

mPDF

mPDF

mPDF is a PHP library that can generate PDF files from UTF-8 encoded HTML. The original author, Ian Back, wrote mPDF to output PDF files "on the fly" from his website and handle different languages. It is slower than original scripts like HTML2FPDF and produces larger files when using Unicode fonts, but supports CSS styles etc. and has a lot of enhancements. Supports almost all languages, including RTL (Arabic and Hebrew) and CJK (Chinese, Japanese and Korean). Supports nested block-level elements (such as P, DIV),