什么是副作用?
我们通常把“函数”定义为:接受输入(参数),经过计算后返回输出(返回值)的过程。如果一个函数除了这个过程之外,还依赖于输入参数以外的状态,或者对程序本身造成了可观察到的变化,那么我们就说这个函数有“副作用”。
例子解析
-
有副作用的函数:
function addTodo(todo) { todos.push(todo); }这个函数依赖于外部的
todos变量(不是通过参数传入的),并且通过push方法修改了todos的内容。这两个行为都属于副作用。 -
依赖外部状态的函数:
function getGithubProfile(username) { return fetch( `https://api.github.com/users/${username}` ).then((res) => res.json()); }这个函数没有直接修改程序的状态,但它依赖于外部的 API(即外部状态),这也算作副作用。
-
修改外部状态的函数:
function updateDocumentTitle(title) { document.title = title; }这个函数没有依赖外部状态(只用到了参数),但它修改了
document.title,即对外部环境产生了可观察的变化,因此也有副作用。
为什么副作用“有问题”?
副作用并不是“坏”的,但它们会让代码变得不可预测。因为副作用依赖于函数外部的上下文(比如全局变量、外部 API、浏览器环境等),如果这些外部状态发生变化,函数的行为也会随之变化,导致结果不可控。
比如:
function calculateFinalPrice(price, qty) {
const total = price * qty
return total * (1 + TAX_RATE)
}
这个函数依赖于外部变量 TAX_RATE。如果 TAX_RATE 被修改甚至删除,calculateFinalPrice 的行为就会变得不可预测,这就是副作用带来的问题。
总结
副作用指的是函数除了根据输入返回输出之外,还依赖或改变了外部状态。副作用会让代码变得难以预测和维护,但在实际开发中,副作用是不可避免的(比如网络请求、修改页面内容等)。关键在于如何管理和控制副作用,使代码更易于理解和维护。