返回对象的部分属性

5

我有一个扁平化的JavaScript对象,如下:

{ 
  id: 3726492,
  kind: 'user',
  permalink: 'nicholas',
  username: 'Nicholas',
  ...
  a lot more attributes
}

我希望创建一个新对象,它只有原始对象属性的子集。
类似于:
var newObject = oldObject.fields(['id', 'username']);

newObject将是

{ 
  id: 3726492,
  username: 'Nicholas'
}

已经有类似的东西了吗?


1
我觉得原版中没有这个功能。至于辅助库,肯定有至少一个可以实现这个功能的。 - Bartek Banachewicz
5个回答

8

Try this

function pick(data, keys) {
  var result = {};
  
  keys.forEach(function (key) {
    if (data.hasOwnProperty(key)) {
      result[key] = data[key];
    }
  });
  
  return result;
}

var data = { 
  id: 3726492,
  kind: 'user',
  permalink: 'nicholas',
  username: 'Nicholas'
}

var newData = pick(data, ['id', 'kind']);
console.log(newData);

underscorejslodash中有一个方法.pick

var data = { 
  id: 3726492,
  kind: 'user',
  permalink: 'nicholas',
  username: 'Nicholas',
};

var newObject = _.pick(data, 'id', 'username');
console.log(newObject);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore.js"></script>


4
您可以使用Array.prototype.reduce将一个对象通过属性列表缩减为另一个对象:

function subset(obj, propList) {
  return propList.reduce(function(newObj, prop) {
    obj.hasOwnProperty(prop) && (newObj[prop] = obj[prop]);
    return newObj;
  }, {});
}

var obj = { 
  id: 3726492,
  kind: 'user',
  permalink: 'nicholas',
  username: 'Nicholas'
};

var newObj = subset(obj, ['id', 'username']);
console.log(newObj);
document.getElementById('json').innerText = JSON.stringify(newObj);
<pre id="json"></pre>


1
不是内置的,但你可以定义一个简单的函数来完成这个任务:
var original = {a:1112, b:434, c:666, d:222};

function fieldSubset(obj, fields) {
  var subsetClone = {};
  for( var i=0,l=fields.length; i<l; i++) {
    // This can prevent filling undefined as properties
    if(obj.hasOwnProperty(fields[i])) {
      subsetClone[fields[i]] = obj[fields[i]];
    }
  }
  return subsetClone;
}

fieldSubset(original, ["a", "c"]);

您也可以在Object.prototype中使用此方法,但请注意,这可能会与未来版本的JavaScript中的本机API发生冲突:

var original = {a:1112, b:434, c:666, d:222};
Object.defineProperty(Object.prototype, "fieldSubset", { 
  value: function(fields) {
      var subsetClone = {};
      for( var i=0,l=fields.length; i<l; i++) {
        // This can prevent filling undefined as properties
        if(this.hasOwnProperty(fields[i])) {
          subsetClone[fields[i]] = this[fields[i]];
        }
      }
      return subsetClone;
    },
  enumerable: false,
  configurable: true}
);  
original.fieldSubset(["a", "c"]);

1

使用Array.prototype.reduce的一行代码。我们还使用Object.assign。想法是使用过滤器数组中找到的键不断扩展空对象。如果看到,reduce函数需要一个回调函数,其中arg1、arg2、arg3作为第一个参数,并且第二个参数是一个空对象。这个对象将被克隆并通过filters数组中指定的键进行扩展。

var a = { 
  id: 3726492,
  kind: 'user',
  permalink: 'nicholas',
  username: 'Nicholas',
};

var filters = ["id","username","permalink"];

var sub = Object.keys(a).reduce((arg1,arg2,arg3)=>{  var res = {}; if(filters.indexOf(arg2)>=0){  res[arg2] = a[arg2]; } return Object.assign(arg1,res);},{})

console.log(sub);


一行代码可以非常强大。 - geg

0

您并没有具体说明对象键后面的值类型。您目前得到的答案涵盖了浅拷贝和深拷贝。 另一种选择是创建原始对象的视图。如果您有非常大的数据对象,并且不想在内存中复制它们,这将非常有用。

function View(obj, properties) {
  var view = {};
  properties.forEach(function(prop) {
    Object.defineProperty(view, prop, {
      get: function() {
             return obj[prop];
           },
      set: function(val) {
             obj[prop] = val;
           },
      enumerable: true,
      configurable: true
    });
  });
  return view;
}

然后你可以使用你的数据进行操作:

var data = { 
  id: 3726492,
  kind: 'user',
  permalink: 'nicholas',
  username: 'Nicholas',
},
view = new View(data, ['id', 'username']);
view.id; // 3736492
view.username; // Nicholas

当然,你必须意识到,通过view.id = 'something else',你可以改变你的原始对象。但是这很容易避免。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接