Lodash cloneDeep с пропуском undefined - PullRequest
0 голосов
/ 23 октября 2018

Я написал функцию 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 stock

Ответы [ 2 ]

0 голосов
/ 23 октября 2018

Это может быть решено с помощью рекурсивного метода 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>

Вы также можете сделать это в ES6 только через Object.entries & уменьшить :

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 недостаточно и т. Д.

0 голосов
/ 23 октября 2018

Насколько я знаю, _.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>
...