过滤掉对象成员的好习惯用法(javascript)

Good idiom to filter out members of an object (javascript)

本文关键字:惯用法 javascript 习惯 对象 成员 过滤      更新时间:2023-09-26

我想删除对象的某些成员(为了参数起见,那些键以'_'开头的成员)。做这件事有什么优雅的方法?天真的方式是:

for (var i in obj) 
  if (i[0] === '_') 
    delete obj[i];

但是在迭代期间修改底层对象。至少在Node中,我想我可以

Object.keys(obj).forEach(function (i) { if (i[0] === '_') delete obj[i]; });

或者每次用笨拙的嵌套循环删除某个内容时重新启动迭代。

有什么更好的解决方案吗?

编辑:在刚刚的测试中,至少在node.js中,天真的解决方案似乎确实有效。当然有可能。。。in是(要求)安全执行的。有人知道吗?

您不必担心。ECMAScript语言规范第12.6.4节的摘录明确指出(我强调):

枚举属性的机制和顺序(第一算法,第二算法中的步骤7.a)。枚举过程中可能会删除被枚举对象的属性。如果在枚举被删除,则不会访问它如果是新的在枚举,不保证新添加的属性在活动枚举中访问。不得访问属性名称在任何枚举中都不止一次。

为什么不像一样创建一个要删除的名称列表

var l = [];
for (var i in obj) 
  if (i[0] === '_') 
    l.push(i);
l.forEach(function(v){ delete obj[v]; });
Object.keys(obj).filter(function (v) {
    return v[0] === "_";
}).forEach(function (v) {
    delete obj[v];
});

不过,这将在循环过程中修改对象;p

如果你不止一次使用这个,通用的是:

Object.keys(obj).filter(function (v) {
    //filter the object values/keys by some conditions
}).forEach( del.bind(obj) );
function del (v) {
    delete this[v];
}

另一种选择是创建一个返回过滤对象的函数。为了避免对代码中引用被修改对象的其他部分产生附带影响,我更喜欢这种解决方案。

function filterObject(obj) {
  var filtered = new Object();
  for (var i in obj)
    if (i[0] != '_')
      filtered[i] = obj[i];
    return filtered;
}