我编写了一个customozer函数,以cloneDeepWith
省略对象的未定义值。但是,对于不变的收益,它不是递归地进行挖掘的。这是我的代码:
import { cloneDeepWith, pickBy, omit } from 'lodash';
const obj = {
a0: true,
b0: true,
c0: undefined,
obj1: {
a1: true,
b1: true,
c1: undefined
}
};
cloneDeepWith(obj, value => {
const objWithUndefinedValue = pickBy(obj, (value) => value === undefined);
const keysWithUndefinedValue = Object.keys(objWithUndefinedValue);
return omit(obj, keysWithUndefinedValue);
});
但是,第一次返回后它不会递归。可以使用lodash的股票功能来完成此任务吗?
答案 0 :(得分:5)
据我所知_.cloneDeepWith()
定制器有点误导。定制程序应仅处理非对象值。如果它处理对象值,则它还应该自己继续递归。例如,您可以看到在调用定制程序时,克隆由value.cloneNode(true)
处理。如您所见,控制台中仅显示body
。
const { cloneDeepWith, isObject } = _;
function customizer(value) {
console.log(value);
if (_.isElement(value)) {
return value.cloneNode(true);
}
}
var el = _.cloneDeepWith(document.body, customizer);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
但是,如果您只是自定义非对象值,并为对象值返回undefined
,这会提示该方法来处理它们(在cloneDeep中进行了记录),则会迭代所有内容:
const { cloneDeepWith, isObject, isUndefined } = _;
const obj = {
a0: true,
b0: true,
c0: undefined,
obj1: {
a1: true,
b1: true,
c1: undefined
}
};
const result = cloneDeepWith(obj, v => {
console.log(v);
return isObject(v) ? undefined : 'custom value';
});
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
要解决您的问题,您可以递归使用_.transform()
来获取所有非undefined
的值:
const { transform, isObject, isUndefined } = _;
const obj = {
a0: true,
b0: true,
c0: undefined,
obj1: {
a1: true,
b1: true,
c1: undefined
}
};
const cloneDeepWithoutUndefined = (obj) =>
transform(obj, (r, v, k) => {
if(isUndefined(v)) return;
r[k] = isObject(v) ? cloneDeepWithoutUndefined(v) : v;
});
const result = cloneDeepWithoutUndefined(obj);
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
答案 1 :(得分:1)
可以通过以下方式使用递归lodash transform方法来解决此问题:
const obj = { a0: true, b0: true, c0: undefined, obj1: { a1: true, b1: true, c1: undefined } };
const cloneMe = (obj) => _.transform(obj, (r, v, k) =>
_.isUndefined(v) ? null : _.isObject(v) ? r[k] = cloneMe(v) : r[k] = v, {})
console.log(cloneMe(obj))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
您还可以仅通过Object.entries和reduce在ES6中执行此操作:
const obj = { a0: true, b0: true, c0: undefined, obj1: { a1: true, b1: true, c1: undefined } };
const cloneMe = (obj) => {
return Object.entries(obj).filter(([k,v]) =>
v != undefined).reduce((r,[k,v]) => {
r[k] = (v instanceof Object) ? cloneMe(v) : v
return r
},{})
}
console.log(cloneMe(obj))
如果instance of Object
不足等,您还可以扩展对对象的检查。
答案 2 :(得分:1)
还有另一种使用DeepDash的方法,它是一个独立的补充库,提供递归版本的Lodash函数。
将DeepDash与Lodash(deepdash(_)
)混合后,您可以编写一个prune
函数,如下所示:
const prune = obj => _.filterDeep(obj, (v) => !_.isUndefined(v))