uniq
baseUniq的实现是uniqBy(iteratee)和uniqWith(comparator)的基础所以很有必要搞懂
import SetCache from './SetCache.js' // 基于Hash的缓存结构
import arrayIncludes from './arrayIncludes.js' // 判断某个元素是否在数组中
import arrayIncludesWith from './arrayIncludesWith.js' // 判断某个元素(符合comparator条件)的元素是否在数组中
import cacheHas from './cacheHas.js' // 判断该缓存是否有某个元素
import createSet from './createSet.js' // 创建一个set数据结构(内部对+0 -0作统一处理)
import setToArray from './setToArray.js' // set 转 array
/** Used as the size to enable large array optimizations. */
const LARGE_ARRAY_SIZE = 200 // 大数组的最大容量
/**
* The base implementation of `uniqBy`.
*
* @private
* @param {Array} array The array to inspect.
* @param {Function} [iteratee] The iteratee invoked per element.
* @param {Function} [comparator] The comparator invoked per element.
* @returns {Array} Returns the new duplicate free array.
*/
function baseUniq(array, iteratee, comparator) {
let index = -1
let includes = arrayIncludes
let isCommon = true // 普通去重(没有comparator 不是大数组)
const { length } = array
const result = []
let seen = result // seen 默认指向result
if (comparator) { // 有比较器情况
isCommon = false
includes = arrayIncludesWith // 由于有comparator实参,相应的include变成带with的
}
else if (length >= LARGE_ARRAY_SIZE) { // 大数组情况
const set = iteratee ? null : createSet(array)
if (set) { // 没有iteratee则直接利用set的去重机制
return setToArray(set)
}
isCommon = false
// 采用hash cache 优化(空间换时间)
includes = cacheHas
seen = new SetCache
}
else { // 无比较器且数组不大情况
// 有iteratee那么seen变成空数组,没有则还是指向result
seen = iteratee ? [] : result
}
outer:
while (++index < length) {
let value = array[index]
const computed = iteratee ? iteratee(value) : value
value = (comparator || value !== 0) ? value : 0 // 无comparator的情况下,把+0 -0转换为0(参考SameValueZero的实现)
if (isCommon && computed === computed) { // 非NaN且是普通比较(无comparator && 大数组)
// 从尾到头检查(emmm难道有啥特殊意义吗?)
let seenIndex = seen.length
while (seenIndex--) {
console.log(seen[seenIndex])
if (seen[seenIndex] === computed) {
continue outer // 遇到重复重复元素,跳出本次循环
}
}
if (iteratee) {
seen.push(computed)
}
result.push(value)
}
else if (!includes(seen, computed, comparator)) { // NaN || 有comparator 情况
// console.log(computed)
if (seen !== result) { // seen初始是一个空cache(针对大数组)或者空数组(针对存在iteratee的情况)
seen.push(computed)
}
result.push(value)
}
}
return result
}
// console.log(baseUniq([1, 2, 3]))
// console.log(baseUniq([NaN, NaN]))
export default baseUniq
不是很懂为啥55行那里要从最后开始检查?等一个大佬解答。感觉自己逻辑有点混乱,上面注释可能写的比较磕碜,希望有大佬指教洛洛洛

本文探讨lodash库中uniq函数的实现原理,重点关注baseUniq作为uniqBy和uniqWith基础的重要性。作者提出疑问,为何在源码的特定部分选择从后往前检查元素,并期待社区专家的解答和指导。
3098

被折叠的 条评论
为什么被折叠?



