Я написал функцию 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?
Насколько я знаю, _.cloneDeepWith()
customizer немного вводит в заблуждение. Настройщик должен обрабатывать только значения, отличные от объекта. Если он обрабатывает значения объекта, он также должен продолжить рекурсию. Например, вы можете видеть, что при вызове customizer клонирование обрабатывается 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>
Это можно решить с помощью метода рекурсивного преобразования lodash с помощью:
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>
Вы также можете сделать это в ES6 только через Object.entries & reduce:
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
недостаточно и т.д.