# 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赋值给nestedwhile循环进行路径的设置,结束条件为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 →