如何从对象中删除递归的未定义属性 - 同时保留构造函数链?

use*_*222 10 javascript lodash

这是一个类似于如何使用lodash从对象中删除未定义和空值的问题?.但是,那里提出的解决方案并不保留构造函数.除此之外,我想只删除那些以'_'开头的键.

这是我正在寻找的,似乎无法从lodash获得:

输入: new Cons({key1 : 'value1', key2 : {key21 : 'value21', _key22: undefined}, key3: undefined, _key4 : undefined})

输出: {key1 : 'value1', key2 : {key21 : 'value21'}, key3: undefined}

例如 function Cons(obj){_.extend(this, obj)}

我有一个omitBy使用lodash 的解决方案,但是,我松开了构造函数信息(即我不能再使用它instanceof Cons来区分对象构造函数).forIn看起来像是递归遍历的一个很好的候选者,但它只为我提供了valuekey.我还需要路径才能删除对象(带unset).

请注意:

  • 该对象是任何有效的JavaScript对象
  • 构造函数是任何 javascript有效的构造函数,该对象随附已经设置的构造函数.
  • 生成的对象必须instanceof whatevertheconstructorwas仍为true

有没有更好的解决方案(使用lodash或其他方式)?

rye*_*lar 9

您可以通过使用omitBy()mapValues()作为递归遍历键的辅助函数来创建递归省略键的函数.另请注意,这也支持具有嵌套数组的对象的数组遍历或具有嵌套对象的顶级数组.

function omitByRecursively(value, iteratee) {
  var cb = v => omitByRecursively(v, iteratee);
  return _.isObject(value)
    ? _.isArray(value)
      ? _.map(value, cb)
      : _(value).omitBy(iteratee).mapValues(cb).value()
    : value;
}

function Cons(obj) { 
  _.extend(this, omitByRecursively(obj, (v, k) => k[0] === '_'));
}
Run Code Online (Sandbox Code Playgroud)

例:

function omitByRecursively(value, iteratee) {
  var cb = v => omitByRecursively(v, iteratee);
  return _.isObject(value)
    ? _.isArray(value)
      ? _.map(value, cb)
      : _(value).omitBy(iteratee).mapValues(cb).value()
    : value;
}

function Cons(obj) { 
  _.extend(this, omitByRecursively(obj, (v, k) => k[0] === '_'));
}

var result = new Cons({
  key1 : 'value1', 
  key2 : {
    key21 : 'value21', 
    _key22: undefined
  }, 
  key3: undefined,
  _key4 : undefined,
  key5: [
    {
      _key: 'value xx',
      key7: 'value zz',
      _key8: 'value aa'
    }
  ]
});

console.log(result);
Run Code Online (Sandbox Code Playgroud)
.as-console-wrapper{min-height:100%;top:0}
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.12.0/lodash.js"></script>
Run Code Online (Sandbox Code Playgroud)


更新

您可以通过创建一个函数来改变对象本身,该函数使用each()递归遍历对象,并通过unset()解决删除问题.

function omitByRecursivelyInPlace(value, iteratee) {

  _.each(value, (v, k) => {

    if(iteratee(v, k)) {
      _.unset(value, k); 
    } else if(_.isObject(v)) {
      omitByRecursivelyInPlace(v, iteratee);  
    }

  });

  return value;

}

function Cons(obj){_.extend(this, obj)}

var result = omitByRecursivelyInPlace(instance, (v, k) => k[0] === '_');
Run Code Online (Sandbox Code Playgroud)

function omitByRecursivelyInPlace(value, iteratee) {
  
  _.each(value, (v, k) => {
    
    if(iteratee(v, k)) {
      _.unset(value, k); 
    } else if(_.isObject(v)) {
      omitByRecursivelyInPlace(v, iteratee);  
    }
    
  });
  
  return value;
  
}

function Cons(obj){_.extend(this, obj)}

var instance = new Cons({
  key1 : 'value1', 
  key2 : {
    key21 : 'value21', 
    _key22: undefined
  }, 
  key3: undefined,
  _key4 : undefined,
  key5: [
    {
      _key: 'value xx',
      key7: 'value zz',
      _key8: 'value aa'
    }
  ]
});

var result = omitByRecursivelyInPlace(instance, (v, k) => k[0] === '_');

console.log(result instanceof Cons);
console.log(result);
Run Code Online (Sandbox Code Playgroud)
.as-console-wrapper{min-height:100%;top:0}
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.12.0/lodash.js"></script>
Run Code Online (Sandbox Code Playgroud)