Home >Web Front-end >JS Tutorial >5 Ways to Make Your JavaScript More Functional

5 Ways to Make Your JavaScript More Functional

Joseph Gordon-Levitt
Joseph Gordon-LevittOriginal
2025-02-09 09:40:13941browse

5 Ways to Make Your JavaScript More Functional

This article will briefly introduce the concept of functional programming and explain five ways to improve the functional style of JavaScript code.

Core points

  • Functional programming is a programming paradigm that uses functions and their applications rather than command lists. It is more abstract and originated from mathematics. JavaScript is particularly suitable for functional programming because functions are the first type of objects.
  • Pure functions are a key part of functional programming. Given the same arguments, they always return the same value and do not change what is outside the scope of the function. They make your code easier to port and test.
  • In functional programming, variables should remain unchanged. After setting the variable, it should remain that state throughout the program. This can be achieved by always declaring variables using const.
  • It is recommended to use arrow functions and ternary operators in JavaScript's functional programming. The arrow functions have implicit return values, which helps visualize the input-to-output mapping. The ternary operator is an expression that always returns a value, so it is useful to ensure that the return value exists.
  • Use for loops in functional programming should be avoided because they depend on mutable states. Recursive and higher-order array methods should be used instead. Additionally, type coercion should be avoided to maintain type consistency. This can be done by writing type declaration comments before declaring the function.

What is functional programming?

Functional programming is a programming paradigm that uses functions and their applications, rather than a list of commands used in the imperative programming language.

This is a more abstract style of programming, with roots in mathematics—particularly the mathematical branch called lambda calculus, designed by mathematician Alonzo Church in 1936 as a formal model of computationality. It consists of expressions and functions that map one expression to another. Basically, this is what we do in functional programming: we use functions to convert values ​​to different values.

The author of this article has fallen in love with functional programming in recent years. We started using JavaScript libraries that encourage more functional styles and then jumped straight into the deep water by learning how to write code in Haskell.

Haskell is a purely functional programming language developed in the 1990s, similar to Scala and Clojure. With these languages, you will be forced to encode in a functional style. Learning Haskell gives us a real understanding of all the benefits of functional programming.

JavaScript is a multi-paradigm language because it can be used to program in an imperative, object-oriented, or functional style. However, it does fit particularly well with the functional style, because functions are first-class objects, which means they can be assigned to variables. This also means that functions can be passed as arguments to other functions (usually called callbacks) or as return values ​​for other functions. Functions that return other functions or accept other functions as parameters are called higher-order functions, and they are the basic part of functional programming.

In recent years, programming JavaScript in a functional style has become increasingly popular, especially after the rise of React. React uses a declarative API that is suitable for functional methods, so a solid grasp of functional programming principles will improve your React code.

Why is functional programming so excellent?

In short, functional programming languages ​​often lead to the code being concise, clear and elegant. The code is usually easier to test and can run in a multi-threaded environment without any problems.

If you talk to many different programmers, you may get completely different opinions about functional programming from everyone – from those who absolutely hate it to those who absolutely love it. We (the author of this article) are on the side of "love it", but we fully understand that it is not everyone's dish, especially since it is very different from the way we usually teach.

But once you master functional programming, and once the thinking process clicks in place, it becomes second nature and changes the way you write your code.

Rule 1: Purify your function

The key part of functional programming is to make sure the functions you write are "pure". If you are not familiar with this term, pure functions basically meet the following conditions:

  • It has citation transparency. This means that, given the same argument, the function will always return the same value. Any function call can be replaced with the return value, and the program will still run the same way. It has no side effects. This means that the function does not make any changes outside the scope of the function. This may include changing the global value, recording to the console, or updating the DOM.
  • Pure function
must have at least one parameter, and

must return a value. If you think carefully, if they don't accept any parameters, they won't have any data to use, and if they don't return values, what's the point of the function? Pure functions may not seem completely necessary at the beginning, but using impure functions will cause overall changes in the program, resulting in some serious logical errors! Example:

In impure functions, the

function depends on the mutable variable

. For example, if the
<code class="language-javascript">// 不纯
let minimum = 21;
const checkAge = (age) => age >= minimum;

// 纯
const checkAge = (age) => {
    const minimum = 21;
    return age >= minimum;
};</code>
variable is updated later in the program, the

function might return a Boolean using the same input. checkAge minimumSuppose we run the following code: minimum checkAge

Now, suppose that later in the code, the

function updates the value of

to 18.
<code class="language-javascript">checkAge(20); // false</code>

Then, suppose we run the following code:

<code class="language-javascript">// 不纯
let minimum = 21;
const checkAge = (age) => age >= minimum;

// 纯
const checkAge = (age) => {
    const minimum = 21;
    return age >= minimum;
};</code>

The checkAge function is now evaluated to different values, although the same input is given.

Pure functions make your code easier to port because they do not depend on any other value other than any value provided as parameters. The fact that the return value never changes makes pure functions easier to test.

Writing pure functions consistently also eliminates the possibility of mutations and side effects.

Mutations are a big red flag in functional programming, and if you want to learn more, you can read about them in the Guide to Variable Assignment and Mutation in JavaScript.

To make your function easier to port, make sure your function is always pure.

Rule 2: Keep the variable unchanged

Declaring variables is one of the first things any programmer learns. It becomes trivial, but it is extremely important when using functional programming styles.

One of the key principles of functional programming is that once a variable is set, it will remain that state throughout the program.

This is the easiest example of how reassignment/redeclaration of variables in your code can be a disaster:

<code class="language-javascript">checkAge(20); // false</code>

If you think about it carefully, the values ​​of n cannot be both 10 and 11; this does not make logical sense.

A common coding practice in imperative programming is to use the following code to increment the value:

<code class="language-javascript">checkAge(20); // true</code>

In mathematics, the statement x = x 1 is illogical because if you subtract x from both sides, you will get 0 = 1, which is obviously incorrect.

Therefore, in Haskell, you cannot assign a variable to a value and then reassign it to another value. To achieve this in JavaScript, you should follow the rules that always use const to declare variables.

Rule 3: Use the arrow function

In mathematics, the concept of a function is the concept of mapping one set of values ​​to another. The following figure shows a function that maps the value set on the left to the value set on the right through squared:

5 Ways to Make Your JavaScript More Functional

This is how you write it in mathematics using arrow notation: f: x → x². This means that the function f maps the value x to x².

We can write this function in almost the same way using the arrow function:

<code class="language-javascript">const n = 10;
n = 11; // TypeError: "Attempted to assign to readonly property."</code>

A key feature of using functional style in JavaScript is the use of arrow functions rather than regular functions. Of course, this does boil down to style, using arrow functions instead of regular functions does not actually affect the degree of "functional" of the code.

However, one of the hardest things to adapt to when using functional programming styles is the way of thinking about each function as a mapping input to output. There is no so-called process. We found that using arrow functions can help us better understand the process of functions.

The arrow function has an implicit return value, which does help visualize this map.

The structures of arrow functions—especially their implicit return values—help encourage writing pure functions, because their structure is actually "input mapped to output":

<code class="language-javascript">// 不纯
let minimum = 21;
const checkAge = (age) => age >= minimum;

// 纯
const checkAge = (age) => {
    const minimum = 21;
    return age >= minimum;
};</code>

Another thing we like to emphasize, especially when writing arrow functions, is to use ternary operators. If you are not familiar with ternary operators, they are inline if...else statements in the form condition ? value if true : value if false.

You can read more about them in Quick Tips: How to Use Tripartite Operators in JavaScript.

One of the main reasons for using ternary operators in functional programming is the necessity of else statements. The program must know what to do if the original conditions are not met. For example, Haskell enforces a statement, and if no else statement is given, it returns an error. else

Another reason to use ternary operators is that they are expressions that always return values, rather than

statements that can be used to perform operations that may have side effects. This is especially useful for arrow functions, as it means you can ensure that the return value exists and keep the image input to the output map. If you are not sure about the nuance between statements and expressions, a guide on statements and expressions is well worth reading. if-else

To illustrate these two conditions, the following is an example of a simple arrow function using the ternary operator:

The
<code class="language-javascript">checkAge(20); // false</code>

function will return the value of "eat" or "sleep" based on the value of the action parameter. state

So, in short: when making your code more functional, you should follow these two rules:

    Writing functions using arrow notation
  • Replace the
  • statement with the ternary operator if...else

Rule 4: Delete the for loop

Given that writing iterative code using

is very common in programming, it seems strange to say that you want to avoid them. In fact, when we first discovered that Haskell didn't even have any kind of for loop operation, we had a hard time understanding how to implement some standard operations. However, there are some very good reasons why for loops don't appear in functional programming, and we quickly discovered that every type of iteration can be implemented without using for loops. for

Not used

The most important reason why loops are looped is that they rely on mutable states. Let's look at a simple sum function: for

<code class="language-javascript">checkAge(20); // true</code>
As you can see, we have to use

in the for loop itself and in the variables we update in the for loop. let

As mentioned earlier, this is usually a bad practice in functional programming, because all variables in functional programming should be immutable.

If we want to write code where all variables are immutable, we can use recursion:

<code class="language-javascript">const n = 10;
n = 11; // TypeError: "Attempted to assign to readonly property."</code>
As you can see, no variables are updated.

The mathematicians among us will obviously know that all of this code is unnecessary, because we can just use the clever summing formula 0.5*n*(n 1). But this is a great way to illustrate the difference between variability of a loop and recursion. for

However, recursion is not the only solution to the variability problem, especially when dealing with arrays. JavaScript has many built-in higher-order array methods that iterate through values ​​in an array without changing any variables.

For example, suppose we want to add 1 to each value in the array. Using the imperative method and the

loop, our function might look like this: for

<code class="language-javascript">// 不纯
let minimum = 21;
const checkAge = (age) => age >= minimum;

// 纯
const checkAge = (age) => {
    const minimum = 21;
    return age >= minimum;
};</code>
However, we can use JavaScript's built-in

method and write a function like this: map

<code class="language-javascript">checkAge(20); // false</code>
If you've never seen

functions before, it's definitely worth knowing about them -- and all the built-in high-order array methods of JavaScript, such as map, especially if you really have a sense of functional programming in JavaScript interest. You can find more about them in Immutable Array Methods: How to Write Very Clear JavaScript Code. filter

Haskell has no

loop at all. To make your JavaScript more functional, try to avoid using for loops by using recursive and built-in higher-order array methods. for

Rule 5: Avoid type mandatory

It is easy to forget the importance of data types when programming in languages ​​such as JavaScript that do not require type declarations. The seven primitive data types used in JavaScript are:

    Number
  • String
  • Boolean
  • Symbol
  • BigInt
  • Undefined
  • Null
Haskell is a strongly typed language that requires type declarations. This means that before any function, you need to use the Hindley-Milner system to specify the data type entering and the data type output.

Example:

<code class="language-javascript">checkAge(20); // true</code>
This is a very simple function that adds two numbers (x and y) together. For every function, including very simple functions like this, it seems a bit ridiculous to have to explain the data type to the program, but this ultimately helps to show how the function is expected to work and what it is expected to return. This makes the code easier to debug, especially if the code becomes more complex.

Type declaration follows the following structure:

Type force can be a big problem when using JavaScript, which has various tricks that can be used (even

abuse
<code class="language-javascript">const n = 10;
n = 11; // TypeError: "Attempted to assign to readonly property."</code>
) to bypass inconsistencies in data types. Here are the most common tips and how to avoid them:

Connection. "Hello" 5 is evaluated as "Hello5", which is not consistent. If you want to concatenate strings with numeric values, you should write "Hello" String(5).

    Boolean statement and 0. In JavaScript, the value 0 in the
  • statement is equivalent to false. This can lead to lazy programming techniques that ignore checking whether the numerical data is equal to 0.
  • ifExample:
<code class="language-javascript">// 不纯
let minimum = 21;
const checkAge = (age) => age >= minimum;

// 纯
const checkAge = (age) => {
    const minimum = 21;
    return age >= minimum;
};</code>

This is a function that evaluates whether a number is an even number. It uses the ! symbol to cast the result of n % 2 to a boolean, but the result of n % 2 is not a boolean, but a number (0 or 1).

Tips like this, while seemingly clever and reduce the amount of code you write, they break the type consistency rules of functional programming. Therefore, the best way to write this function is as follows:

<code class="language-javascript">checkAge(20); // false</code>

Another important concept is to ensure that all data values ​​in the array are of the same type. JavaScript does not enforce this, but if there is no same type, it can cause problems when you want to use higher-order array methods.

For example, a product function that multiplies all numbers in an array and returns the result can be written with the following type declaration annotation:

<code class="language-javascript">checkAge(20); // true</code>

Here, the type declaration clearly states that the input of the function is an array containing elements of type Number, but it returns only one number. The type declaration clearly illustrates the expected input and output of this function. Obviously, this function won't work if the array contains more than just numbers.

Haskell is a strongly typed language, while JavaScript is a weakly typed language, but to make your JavaScript more functional, you should write type declaration comments before declaring your function and make sure to avoid type-forced shortcuts.

We should also mention here that if you want a strongly typed alternative to JavaScript that will enforce type consistency for you, you can turn to TypeScript.

Conclusion

All in all, the following five rules will help you implement functional code:

  • Keep your functionpure.
  • Always declare variables and functions using const.
  • Use the arrow notation for the function.
  • Avoid using for Loop.
  • Use type declaration annotations and avoid type forced shortcuts.

While these rules don't guarantee that your code is purely functional, they will make it more functional to a large extent and help make it cleaner, clearer and easier to test.

We really hope these rules will help you as much as we can! Both of us are big fans of functional programming and we highly recommend that any programmer use it.

If you want to dig deeper into functional JavaScript, we strongly recommend that you read "Most of the Sufficient Guide to Functional Programming by Professor Frisby, which is available online for free. If you want to go all out to learn Haskell, we recommend using the Try Haskell interactive tutorial and reading the excellent book Learn Haskell for Greater Benefits, which is also available for free online.

Frequently Asked Questions about JavaScript Functional Programming

What is functional programming in JavaScript? Functional programming is a programming paradigm that treats calculations as evaluations of mathematical functions and avoids changing states and mutable data. In JavaScript, it involves using functions as first-class citizens and avoiding side effects.

What is a first-class function in JavaScript? A first-class function in JavaScript means that the function is treated as the same as any other variable. They can be assigned values ​​to variables, passed as parameters to other functions, and returned as values ​​from other functions.

What is invariance in functional programming? Invariance means that once an object is created, it cannot be changed. In the context of JavaScript functional programming, this means avoiding modifying variables or data structures after initializing them.

What is a higher-order function? A higher-order function is a function that takes other functions as parameters or returns functions as results. They support combinations of functions, making it easier to create modular and reusable code.

Is there any library/framework that facilitates functional programming in JavaScript? Yes, some libraries and frameworks (such as Ramda and lodash) provide utilities and functions that support the concept of JavaScript functional programming. They can help simplify and enhance functional programming practices.

The above is the detailed content of 5 Ways to Make Your JavaScript More Functional. 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