# baseSet
# Description
将 value 值 设置到 object path 路径的 key 上
# Params
(object, path, value, customizer)
{Object} object - 要修改的对象。
{Array|string} path - 要设置的属性的路径。
{Function} [customizer] - 自定义创建路径。
# Return
Object
# Depend
import assignValue from './assignValue.js'
import castPath from './castPath.js'
import isIndex from './isIndex.js'
import isObject from '../isObject.js'
import toKey from './toKey.js'
assignValue 源码分析
castPath 源码分析
isIndex 源码分析
isObject 源码分析
toKey 源码分析
# Code
function baseSet(object, path, value, customizer) {
if (!isObject(object)) {
return object
}
path = castPath(path, object)
const length = path.length
const lastIndex = length - 1
let index = -1
let nested = object
while (nested != null && ++index < length) {
const key = toKey(path[index])
let newValue = value
if (index != lastIndex) {
const objValue = nested[key]
newValue = customizer ? customizer(objValue, key, nested) : undefined
if (newValue === undefined) {
newValue = isObject(objValue)
? objValue
: (isIndex(path[index + 1]) ? [] : {})
}
}
assignValue(nested, key, newValue)
nested = nested[key]
}
return object
}
# Analyze
首先判断如果不是
object
类型,则直接返回使用
castPath
将path
转换为 路径数组,拿到length
,拿到最后一个元素的索引lastIndex
, 将object
赋值给nested
while
循环进行路径的设置,结束条件为nested != null && ++index < length
首先将当前 路径转换为对象可设置的
key
,在不是最后一个元素时,newValue
会等于objValue
或者空数组或空对象,具体判断条件如下- 判断当前
index
不是最后一个元素的索引 nested
一开始设置的值是传入的object
,所以这里nested[key]
可能有值,也可能为undefined
- 如果传入了
customizer
函数,则使用customizer
进行值的处理,否则newValue
设置为undefined
- 即使经过
customizer
的处理,newValue
也有可能为undefined
- 所以判断如果
newValue
为undefined
,则判断nested[key]
也就是objValue
是否为object
类型,如果是object
类型则表示可以设置属性,将objValue
赋值给newValue
- 否则
objValue
不能为其设置属性,则需要将其设置为object
类型 - 这里判断了
isIndex(path[index + 1]
,是为了判断 其 下一层是对象的子级还是数组的子级 ,对应设置当前层为空数组或空对象
- 判断当前
在处理完成上述条件后,会使用
assignValue
进行赋值操作,如果之前对象对应的子级就是引用类型,则不会进行更改(newValue = isObject(objValue) ? objValue : ...
),否则会为其设置相应的子级为 数组 或 对象拿到要设置的下一层,赋值给
nested
,继续进行while
循环的判断如果到了最后一个元素,则不会进行第四步的判断及处理,直接将传入的
value
的值,设置到对应的位置即可因为一直是引用类型,所以最终会改变 传入的
object
,所以最后返回object
即可
# Remark
主要就是拿到
path
的数组,然后遍历数组进行赋值操作 ,如果传入的对象本身就有path
数组中的key
,而且也是引用类型,那其实没有改变,到最后只是设置值罢了;如果不是的话,那就会将其改变了
e.g
const a = { b: { c: 3}} baseSet(a, 'a.b.c', 4)
如果是这样,那在
while
循环的if
判断里,其实获取nested[key]
这里,拿到的就是一个object
类型如果传入的对象本身没有对应的 key ,或者对应的 key 不是最后一层,还不是引用类型,那就会改变了
e.g
const a = {} baseSet(a, 'a.b.c', 4)
那这个时候就会改变 原对象了,会将其对应 key ,如不是最后一层,会设置为 空对象 或 空数组
# Example
const a = {b:3}
console.log(baseSet(a, 'b.c', 4)) // { b: { c: 4 } }
← baseReduce baseSortBy →