tree-shaking的副作用(side effects)

1,400 阅读3分钟

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.logalert等。

抛出异常

抛出错误或异常也是一种副作用。

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