本文为读 lodash 源码的第三百零四篇,后续文章会更新到这个仓库中,欢迎 star:pocket-lodash
gitbook也会同步仓库的更新,gitbook地址:pocket-lodash
import arrayEach from './.internal/arrayEach.js'
import baseForOwn from './.internal/baseForOwn.js'
import isBuffer from './isBuffer.js'
import isObject from './isObject.js'
import isTypedArray from './isTypedArray.js'
transform
的作用跟 reduce
差不多,会将 object
转换成一个新的 accumulator
对象,如果 accumulator
没有传入时,会创建一个和 object
的 [[Prototype]]
相同的新对象作为初始值,即两者的原型相同。
源码如下:
function transform(object, iteratee, accumulator) {
const isArr = Array.isArray(object)
const isArrLike = isArr || isBuffer(object) || isTypedArray(object)
if (accumulator == null) {
const Ctor = object && object.constructor
if (isArrLike) {
accumulator = isArr ? new Ctor : []
}
else if (isObject(object)) {
accumulator = typeof Ctor === 'function'
? Object.create(Object.getPrototypeOf(object))
: {}
}
else {
accumulator = {}
}
}
(isArrLike ? arrayEach : baseForOwn)(object, (value, index, object) =>
iteratee(accumulator, value, index, object))
return accumulator
}
if (isArrLike) {
accumulator = isArr ? new Ctor : []
}
如果是数组,则直接调用 new Ctro
,即直接使用原来的构造函数,否则,初始化一个空数组 []
。
else if (isObject(object)) {
accumulator = typeof Ctor === 'function'
? Object.create(Object.getPrototypeOf(object))
: {}
} else {
accumulator = {}
}
如果 Ctro
为函数,即存在构造函数,则调用 Object.create
来得到一个和原 object
同样原型链的新对象。
否则直接使用空对象。
其它情况也使用新对象。
(isArrLike ? arrayEach : baseForOwn)(object, (value, index, object) =>
iteratee(accumulator, value, index, object))
接下来,就根据 object
的类型来选择不同的遍历函数,在遍历的过程中,调用 iteratee
迭代器,传入 accumulator
和 value
、index
及原 object
,可以在 iteratee
里直接修改 accumulator
。
署名-非商业性使用-禁止演绎 4.0 国际 (CC BY-NC-ND 4.0)
最后,所有文章都会同步发送到微信公众号上,欢迎关注,欢迎提意见:
作者:对角另一面