1、什么是tree-shaking的副作用(side effects)
Tree-shaking的副作用(side effects)是指在模块初始化过程中,执行的那些对外部状态产生影响的操作。这些外部状态的改变可能是修改全局变量、执行I/O操作、调用浏览器API等。在JavaScript模块中,即使某些代码或模块未被直接引用,只要它们在加载时执行了这类有副作用的操作,就可能影响到程序的其他部分或整个应用的行为。
在进行tree-shaking时,构建工具会尝试移除未被使用的代码,以减小最终打包文件的体积。然而,如果移除的代码包含有副作用,那么这些副作用也会丢失,可能会导致程序行为的改变。因此,构建工具在处理tree-shaking时,需要特别注意识别和保留那些有副作用的代码。
// 假设这段代码在一个模块中
console.log('这段代码有副作用,因为它改变了外部状态:控制台输出了信息');
export const add = (a, b) => a + b;
2、副作用的范围
修改全局变量或对象
这是最常见的副作用来源,比如修改
window对象上的属性或全局作用域中的变量。
修改函数外部的变量
即使这些变量不是全局的,改变它们的值也会产生副作用。
执行I/O操作
如网络请求、文件读写操作。
调用DOM API
任何对DOM的修改都是副作用,比如创建或修改DOM节点。
调用浏览器API
如
console.log、alert等。
抛出异常
抛出错误或异常也是一种副作用。
3、优化策略
1、使用纯函数
纯函数指的是给定相同的输入,总是返回相同的输出,并且没有任何副作用的函数。
// 纯函数示例
function add(a, b) {
return a + b;
}
console.log(add(2, 3)); // 总是输出5
2、不可变数据结构
避免直接修改数据,而是生成修改后的数据副本。
// 不可变数据结构示例
const originalArray = [1, 2, 3];
// 不直接修改originalArray,而是创建一个新数组
const newArray = [...originalArray, 4]; // [1, 2, 3, 4]
console.log(originalArray); // [1, 2, 3]
console.log(newArray); // [1, 2, 3, 4]
3、限制副作用的范围
将副作用限制在特定的函数或模块中,使得副作用的部分更加明确和集中。
// 副作用函数示例
let count = 0; // 外部变量
function incrementCount() {
count += 1; // 明确的副作用:修改了外部变量
}
console.log(count); // 0
incrementCount();
console.log(count); // 1
4、明确标记有副作用的代码
通过命名约定或文档注释,明确标出那些有副作用的代码部分。
// 外部状态
let state = { count: 0 };
/**
* incrementState - 明确地标记这是一个有副作用的函数,因为它修改了外部状态。
* @returns {void}
*/
function incrementState() {
state.count += 1; // 修改外部状态
}
// 使用前后的state对比,可以看到副作用
console.log(state.count); // 0
incrementState();
console.log(state.count); // 1