# intersectionBy

# Description

这个方法类似 intersection,区别是它接受一个 iteratee 调用每一个 arrays 的每个值以产生一个值,通过产生的值进行了比较。结果值是从第一数组中选择。iteratee 会传入一个参数:(value)。

# Params

arrays

最后一个参数为 iteratee

# Return

Array

# Depend

import map from './map.js'
import baseIntersection from './.internal/baseIntersection.js'
import castArrayLikeObject from './.internal/castArrayLikeObject.js'
import last from './last.js'

map 源码分析

baseIntersection 源码分析

castArrayLikeObject 源码分析

last 源码分析

# Code

function intersectionBy(...arrays) {
  let iteratee = last(arrays)
  const mapped = map(arrays, castArrayLikeObject)

  if (iteratee === last(mapped)) {
    iteratee = undefined
  } else {
    mapped.pop()
  }
  return (mapped.length && mapped[0] === arrays[0])
    ? baseIntersection(mapped, iteratee)
    : []
}

# Analyze

intersection 基本类似,不过这里对于 iteratee 做了处理

首先通过 last 函数,拿到 arrays 的最后一项,定义为 iteratee

然后 通过 mapcastArrayLikeObjectarrays 数组进行处理,拿到返回值 mapped

接着有了一个判断

  if (iteratee === last(mapped)) {
    iteratee = undefined
  } else {
    mapped.pop()
  }

但是这个判断并不严谨,这里只是判断了 iteratee === last(mapped) 的情况下,将 iteratee 置为 undefined

言外之意,如果不等于,lodash 就等同于认定传入了 iteratee 函数,但是这是不对的

intersection 函数中,如果传入这样的值 [1,2,3,4,5], [2,3,4,5,6], 5

intersection([1,2,3,4,5], [2,3,4,5,6], 5)

会得到的是空数组,但是如果在 intersectionBy 中传入,则会报错,因为 lodash 把最后一个参数 5 当做了 iteratee 方法,这个时候 使用 iteratee 去调用时,就会报错

正确的判断应该是和 intersectionWith 一样

  iteratee = typeof iteratee === 'function' ? iteratee : undefined
  if (iteratee) {
    mapped.pop()
  }

应当判断 iteratee 的合法性,所以最终修改为

function intersectionBy(...arrays) {
  let iteratee = last(arrays)
  const mapped = map(arrays, castArrayLikeObject)

  iteratee = typeof iteratee === 'function' ? iteratee : undefined
  if (iteratee) {
    mapped.pop()
  }
  
  return (mapped.length && mapped[0] === arrays[0])
    ? baseIntersection(mapped, iteratee)
    : []
}

# Example

console.log(intersectionBy([1,2,3,4], [2,3,4,5], (v) => v*v)) // [ 2, 3, 4 ]