深入解析 Lodash 的 difference() 函数源码
difference用途
创建一个具有唯一array值的数组,每个值不包含在其他给定的数组中。
代码示例
参数
- array (Array): 要检查的数组。
- [values] (...Array): 排除的值。
const differenceArray = difference([3, 2, 1], [4, 2])
console.log(differenceArray)
// 输出 [ 3,1 ]
源码解析
function difference(array, ...values) {
if (!isArrayLikeObject(array)) {
return [];
}
const flattenedValues = baseFlatten(values, 1, isArrayLikeObject, true);
return baseDifference(array, flattenedValues);
}
现在让我们来分析这段代码:
- 首先,对传入的 array 参数进行检查,确保它是一个类数组对象。如果 array 不是类数组对象,函数将返回一个空数组。
- 调用 baseFlatten 函数对 values 进行扁平化处理,将多维数组转换为一维数组,其中:
- values 是要扁平化的数组。
- 1 表示只扁平化一层。
- isArrayLikeObject 是一个回调函数,用于判断数组或类数组对象。
- true 表示移除扁平化后的数组中的空值。
- 调用 baseDifference 函数,传入 array 和经过扁平化处理的 flattenedValues 作为参数,计算两个数组之间的差异。
- 最后,返回计算结果作为 difference 函数的输出。
值得学习的地方
- 参数合法性检查:在函数开始处对参数进行合法性检查,确保函数能够正常工作并返回正确的结果。
- 模块化设计:函数内部的实现采用了模块化的设计,将差异计算的核心逻辑委托给了 baseDifference 函数,将扁平化处理的逻辑委托给了 baseFlatten 函数。这种模块化的设计使得代码更易于理解、维护和复用。通过将核心逻辑拆分成多个函数,可以提高代码的可读性和可测试性。
- 函数的单一责任原则:difference 函数专注于处理差异计算的逻辑,而将参数检查和扁平化处理的任务委托给其他函数。这遵循了函数的单一责任原则,每个函数只关注一个特定的任务,使得代码更加模块化、可测试和可维护。
改进的地方
随着ES规范的完善可以采用以下方式来实现difference:
function difference(array, ...values) {
if (!Array.isArray(array)) {
throw new TypeError('The first argument must be an array.');
}
if (values.some(value => !Array.isArray(value))) {
throw new TypeError('All values must be arrays.');
}
const valuesSet = new Set(values.flat());
return array.filter(item => !valuesSet.has(item));
}
总结
lodash 中 difference 函数的实现方式展示了一些有价值的编程技巧和设计原则,例如使用剩余参数处理可变数量的参数、模块化设计、合法性检查、扁平化处理、使用高效的数据结构等。这些技巧和原则可以帮助我们编写更灵活、健壮、可维护和高性能的代码。
转载自:https://juejin.cn/post/7248035662074855485