惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

G
Google Developers Blog
S
Schneier on Security
The Hacker News
The Hacker News
P
Proofpoint News Feed
Spread Privacy
Spread Privacy
L
LINUX DO - 热门话题
L
Lohrmann on Cybersecurity
I
Intezer
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Schneier on Security
Schneier on Security
Security Latest
Security Latest
AWS News Blog
AWS News Blog
B
Blog RSS Feed
Microsoft Security Blog
Microsoft Security Blog
有赞技术团队
有赞技术团队
博客园 - 叶小钗
The Last Watchdog
The Last Watchdog
O
OpenAI News
月光博客
月光博客
Hacker News: Ask HN
Hacker News: Ask HN
阮一峰的网络日志
阮一峰的网络日志
S
Security @ Cisco Blogs
Google Online Security Blog
Google Online Security Blog
云风的 BLOG
云风的 BLOG
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Latest news
Latest news
P
Palo Alto Networks Blog
Last Week in AI
Last Week in AI
M
MIT News - Artificial intelligence
Google DeepMind News
Google DeepMind News
P
Proofpoint News Feed
C
CERT Recently Published Vulnerability Notes
Apple Machine Learning Research
Apple Machine Learning Research
U
Unit 42
PCI Perspectives
PCI Perspectives
博客园 - 聂微东
SecWiki News
SecWiki News
宝玉的分享
宝玉的分享
Forbes - Security
Forbes - Security
H
Heimdal Security Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Hugging Face - Blog
Hugging Face - Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
T
Troy Hunt's Blog
博客园 - 三生石上(FineUI控件)
Application and Cybersecurity Blog
Application and Cybersecurity Blog
罗磊的独立博客
WordPress大学
WordPress大学
D
Darknet – Hacking Tools, Hacker News & Cyber Security

Dmitri Pavlutin Blog

Record Type in TypeScript: A Quick Intro How to Write Comments in React: The Good, the Bad and the Ugly 4 Ways to Create an Enum in JavaScript React forwardRef(): How to Pass Refs to Child Components TypeScript Function Types: A Beginner's Guide How to Use v-model to Access Input Values in Vue Mastering Vue refs: From Zero to Hero Environment Variables in JavaScript: process.env 5 Must-Know Differences Between ref() and reactive() in Vue How to Destructure Props in Vue (Composition API) Triangulation in Test-Driven Development How to Use nextTick() in Vue Programming to Interface Vs to Implementation A Smarter JavaScript Mapper: array.flatMap() Array Grouping in JavaScript: Object.groupBy() How to Access ES Module Metadata using import.meta JSON Modules in JavaScript How to Trim Strings in JavaScript TypeScript Function Overloading How to Debounce and Throttle Callbacks in Vue How to Show/Hide Elements in Vue Sparse vs Dense Arrays in JavaScript How to Fill an Array with Initial Values in JavaScript Covariance and Contravariance in TypeScript What are Higher-Order Functions in JavaScript? How to Use TypeScript with React Components Index Signatures in TypeScript How to Use React useReducer() Hook unknown vs any in TypeScript A Guide to React Context and useContext() Hook How to Use Promise.any() 2 Ways to Remove a Property from an Object in JavaScript 'return await promise' vs 'return promise' in JavaScript How to Use Promise.allSettled() How to Use fetch() with JSON JavaScript Promises: then(f,f) vs then(f).catch(f) What is a Promise in JavaScript? How to Use Promise.all() A Simple Guide to Component Props in React Don't Stop Me Now: How to Use React useTransition() hook A Simple Explanation of JavaScript Variables: const, let, var ES Modules Dynamic Import How to Memoize with React.useMemo() How to Cleanup Async Effects in React Why Math.max() Without Arguments Returns -Infinity How to Debounce and Throttle Callbacks in React Don't Confuse Function Expressions and Function Declarations in JavaScript How to Use ES Modules in Node.js Solving a Mystery Behavior of parseInt() in JavaScript How to Use Array Reduce Method in JavaScript 3 Ways to Merge Arrays in JavaScript A Guide to Jotai: the Minimalist React State Management Library The Difference Between Values and References in JavaScript How to Implement a Queue in JavaScript A Helpful Algorithm to Determine "this" value in JavaScript React useRef() Hook Explained in 3 Steps 7 Interview Questions on "this" keyword in JavaScript. Can You Answer Them? How to Greatly Enhance fetch() with the Decorator Pattern 7 Interview Questions on JavaScript Closures. Can You Answer Them? What's a Method in JavaScript? array.sort() Does Not Simply Sort Numbers in JavaScript How to Solve the Infinite Loop of React.useEffect() The New Array Method You'll Enjoy: array.at(index) What's the Difference between DOM Node and Element? Why Promises Are Faster Than setTimeout()? Everything About Callback Functions in JavaScript How React Updates State 5 Mistakes to Avoid When Using React Hooks 5 Best Practices to Write Quality JavaScript Variables Type checking in JavaScript: typeof and instanceof operators 3 Ways to Check if a Variable is Defined in JavaScript React Forms Tutorial: Access Input Values, Validate, Submit Forms Prototypal Inheritance in JavaScript How to Timeout a fetch() Request How to Learn JavaScript If You're a Beginner A Simple Explanation of React.useEffect() A Simple Explanation of JavaScript Iterators How to Use React Controlled Inputs Everything about null in JavaScript How to Use Fetch with async/await Getting Started with Arrow Functions in JavaScript An Interesting Explanation of async/await in JavaScript Front-end Architecture: Stable and Volatile Dependencies Is it Safe to Compare JavaScript Strings? How to Access Object's Keys, Values, and Entries in JavaScript What Actually is a String in JavaScript? 3 Ways to Shallow Clone Objects in JavaScript (w/ bonuses) Checking if an Array Contains a Value in JavaScript JavaScript Event Delegation: A Beginner's Guide How to Parse URL in JavaScript: hostname, pathname, query, hash 3 Ways to Detect an Array in JavaScript How to Get the Screen, Window, and Web Page Sizes in JavaScript 3 Ways to Check If an Object Has a Property/Key in JavaScript How to Compare Objects in JavaScript Object.is() vs Strict Equality Operator in JavaScript Own and Inherited Properties in JavaScript 5 Differences Between Arrow and Regular Functions How to Use Object Destructuring in JavaScript Your Guide to React.useCallback() 5 JavaScript Scope Gotchas
Pure Functions in JavaScript: A Beginner's Guide
Dmitri Pavlutin · 2023-05-15 · via Dmitri Pavlutin Blog

A function is a reusable block of code that accepts arguments and returns a computed value.

A pure function always returns the same value given the same arguments and produces no side effects.

Let's see in more detail what are pure functions and why they are useful.

Table of Contents

  • 1. Pure functions
  • 2. Pure function benefits
  • 3. Impure functions
  • 4. Dealing with impure functions
  • 5. Conclusion

1. Pure functions

A function that returns the sum of 2 numbers is pure:


function sum(a, b) {

return a + b

}

console.log(sum(1, 2)) // logs 3

console.log(sum(1, 2)) // logs 3

console.log(sum(5, 2)) // logs 7

console.log(sum(5, 2)) // logs 7


sum() is a pure function because, given the same numbers, it always returns the same sum.

For example, sum(1, 2) always returns 3, no matter how many times or where the function is called.

Pure function JavaScript

Let's see some more examples of pure functions:


// max of arguments

Math.max(1, 2, 3)

// nearest lowest integer

Math.floor(1.23)

// The multiplication of two numbers

function multiply(a, b) {

return a * b

}

// Summarizing the array items

function sumOfArray(array) {

return array.reduce((sum, item) => sum + item)

}

// Returning a constant value

function answer() {

return 42

}

// Function that returns nothing (noop)

function noop() {

// nothing

}


Now let's look at the second requirement of a pure function: do not produce a side effect.

A side effect is change to external state or environment outside of the function scope. Examples of side effects are:

  • changing variables and objects defined outside the function scope
  • logging to console
  • changing document title
  • DOM manipulations
  • making HTTP requests

If the sum() function logs to the console, then the function is not pure because it produces a side effect:


function sumSideEffect(a, b) {

const s = a + b

console.log(s) // Side effect!

return s

}

console.log(sumSideEffect(1, 2))


sumSideEffect() produces a side effect. It is not a pure function.

Functions that are not pure are called impure. Before looking at the impure functions, let's see what are the benefits of pure functions.

2. Pure function benefits

The main benefit of a pure function is predictability: given the same arguments it always returns the same value.

The pure function is also easy to test. The test just has to supply the right arguments and verify the output:


describe('sum()', () => {

it('should return the sum of two numbers', () => {

expect(sum(1, 2)).toBe(3)

})

})


Because the pure function doesn't create side effects, the test doesn't have to arrange and clean up the side effect.

The pure function that makes computationally expensive calculations can be memoized. Because the single source of truth of a pure function is its arguments they can be used as cache keys during memoization.

factorial() function is a pure function. Because factorial computation is expensive, you can improve the performance of the function by wrapping factorial into a memoize() wrapper (see the npm package):


import memoize from 'lodash.memoize'

function factorial(n) {

if (n === 0) {

return 1

}

return n * factorial(n - 1)

}

const memoizedFactorial = memoize(factorial)

console.log(memoizedFactorial(5)) // logs 120

console.log(memoizedFactorial(5)) // logs 120


Open the demo.

When calling memoizedFactorial(10) the memoized factorial with argument 5, the factorial function itself is going to be invoked and the result is memoized.

Calling again the memoized factorial with the same 5 arguments returns the memoized value right away.

Pure Function are Memoized

Pure functions are easy to compose. Simple pure functions can be composed to create more complex functions.

For example, you can use reuse the pure sum() function to calculate the sum of an array:


function sum(a, b) {

return a + b

}

function sumOfArray(array) {

return array.reduce(sum)

}

console.log(sumOfArray([2, 3])) // logs 5


Pure functions are the base of functional programming. I encourage you to explore the popular functional programming library Ramda, which uses extensively the composition of pure functions.

3. Impure functions

A function that can return different values given the same arguments or makes side effects is named impure function.

In practice, a function becomes impure when it reads or modifies an external state.

A good example of an impure function is the built-in JavaScript random generator Math.random():


console.log(Math.random()) // logs 0.8891108266488603

console.log(Math.random()) // logs 0.9590062769956789


Math.random(), given the same arguments (in this case no arguments at all), returns different numbers smaller than 1. This makes the function impure.

Impure function in JavaScript

Here's another example of an impure function:


let value = 0

function add(increase) {

value += increase // Side-effect

return value

}

console.log(add(2)) // logs 2

console.log(add(2)) // logs 4


add() function is impure because it produces a side effect: modifies value variable accessed from the outer scope. The function also returns different values for the same arguments.

Impure Function with Side Effect

Other examples of impure functions:


function addProperty(object) {

// Mutates the parameter object (side effect)

Object.assign(object, { b: 1 })

}

function deleteById(id) {

// Modifies DOM (side effect)

document.getElementById(id).remove()

}

async function fetchEmployees() {

// Accesses the networks (external state)

const response = await fetch('https://example.com/employees/')

return response.json()

}

function screenSmallerThan(pixels) {

// Accesses the browser page (external state)

const { matches } = window.matchMedia(`(max-width: ${pixels})px`)

return matches

}


These functions are impure because they make side effects like mutating the parameter or DOM and accessing external states like the network and the screen information.

4. Dealing with impure functions

Impure functions have a higher complexity compared to pure functions. Complexity is added by accessing external states or by side effects.

Because of their higher comlexity impure functions are harder to test. You have to mock the external state or the side effect to understand if the function works correctly.

Either way, there's nothing wrong with the impure functions. They are a necessary evil for the application to communicate with the external world.

If you are lucky, some impure functions can be transformed into pure by refactoring mutable operations to immutable.

The following function adds default properties to an object. The function is impure because the parameter original is mutated:


function addDefaultsImpure(original, defaults) {

return Object.assign(original, defaults)

}

const original = { a: 1 }

const result = addDefaultsImpure(original, { b: 2 })

console.log(original) // logs { a: 1, b: 2 }

console.log(result) // logs { a: 1, b: 2 }


Object.assign(object, defaults) mutates original parameter by merging the properties of defaults object into it.

The problem with addDefaultsImpure() is the cognitive load: you have to remember that the argument object is mutated.

Let's make the function pure by using an immutable merge operation:


function addDefaultsPure(original, defaults) {

return Object.assign({}, original, defaults)

}

const original = { a: 1 }

const result = addDefaultsPure(original, { b: 2 })

console.log(original) // logs { a: 1 }

console.log(result) // logs { a: 1, b: 2 }


Object.assign({}, object, defaults) doesn't alter neither original nor defaults objects. It just creates a new object.

addDefaultsPure() is now pure and has no side effects.

Another approach I have found efficient is the extraction of big chunks of pure code from an impure function. Then make the impure function call the extracted pure function.

This gives the benefit of isolating the logic that is understandable and predictable into a pure function. The complexity of the impure function also decreases since it has less code.

5. Conclusion

A function is pure when given the same arguments it always returns the same value and makes no side effects.

Pure functions are easy to understand, easy to test, and can be composed and memoized. Whenever possible, strive to create pure functions.

Impure functions, on the other side, are functions that access external state or produce side effects. Impure functions let your application communicate with the external world.

What other benefits of pure functions do you know?