在 JavaScript 对象中只保留某些属性

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22202766/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 22:40:51  来源:igfitidea点击:

Keeping only certain properties in a JavaScript object

javascript

提问by user1032531

I have an object. I would like to modify the object (not clone it) by removing all properties except for certain specific properties. For instance, if I started with this object:

我有一个对象。我想通过删除除某些特定属性之外的所有属性来修改对象(而不是克隆它)。例如,如果我从这个对象开始:

var myObj={
    p1:123,
    p2:321,
    p3:{p3_1:1231,p3_2:342},
    p4:'23423',
    //....
    p99:{p99_1:'sadf',p99_2:234},
    p100:3434
}

and only want properties p1, p2, and p100, how can I obtain this object:

并且只想要属性 p1、p2 和 p100,我如何获得这个对象:

var myObj={
    p1:123,
    p2:321,
    p100:3434
}

I understand how I could do this with brute force, but would like a more elegant solution.

我明白我如何用蛮力做到这一点,但想要一个更优雅的解决方案。

采纳答案by VisioN

Just re-initialise the object:

只需重新初始化对象:

myObj = {
    p1:   myObj.p1,
    p2:   myObj.p2,
    p100: myObj.p100
};

Another way is to delete certain properties, which is less effective:

另一种方法是删除某些属性,效果较差:

var prop = ['p1', 'p2', 'p100'];
for (var k in myObj) {
    if (prop.indexOf(k) < 0) {
        delete myObj[k];
    }
}

回答by Alf

This was the first hit when googling 'js keep only certain keys' so might be worth an update.

这是谷歌搜索“js 只保留某些键”时的第一次命中,因此可能值得更新。

The most 'elegant' solution might just be using underscore.js

最“优雅”的解决方案可能只是使用 underscore.js

_.pick(myObj, 'p1', 'p2', 'p100')

回答by Grant

Lodashhas a function called pickwhich does what you're describing. I know that including a library isn't ideal, but you can also cherry-pick functions when using bundles, etc.

Lodash有一个名为的函数pick,它执行您所描述的操作。我知道包含库并不理想,但您也可以在使用捆绑包等时挑选功能。

var myObj={
    p1:123,
    p2:321,
    p3:{p3_1:1231,p3_2:342},
    p4:'23423',
    //....
    p99:{p99_1:'sadf',p99_2:234},
    p100:3434
}

var newObj = _.pick(myObj, 'p1', 'p2', 'p100')

回答by Juan Mendes

var myObj = {a: 1, b: 2, c:3};

function keepProps(obj, keep) {
    for (var prop in obj) {
        if (keep.indexOf( prop ) == -1) {
            delete obj[prop];
        }             
    }
}

keepProps(myObj, ['a', 'b']);
console.log(myObj);

http://jsfiddle.net/mendesjuan/d8Sp3/2/

http://jsfiddle.net/mendesjuan/d8Sp3/2/

回答by leaf

You could use delete:

你可以使用delete

for (var k in myObj) {
    if (k !== 'p1' && k !== 'p2' && k !== 'p100') {
        delete myObj[k];
    }
}

An alternative to indexOf:

替代方案indexOf

var keep = /^p(1|2|100)$/;
for (var k in myObj) {
    if (!keep.test(k)) {
        delete myObj[k];
    }
}

Shorter :

更短:

var keep = /^p(1|2|100)$/;
for (var k in myObj) {
    keep.test(k) || delete myObj[k];
}

Array to RegExp :

数组到正则表达式:

var keep = [1, 2, 100];
keep = new RegExp('^p(' + keep.join('|') + ')$'); // /^p(1|2|100)$/
keep.test('p1'); // true
keep.test('p3'); // false

Useful with a function :

对函数有用:

function keep(o, ids) {
    var keep = new RegExp('^p(' + ids.join('|') + ')$');
    for (var k in o) keep.test(k) || delete o[k];
    return o;
}

Usage :

用法 :

keep(myObj, [1, 2, 100]); // { p1: 123, p2: 321, p100: 3434 }


You don't like regular expressions but still want a bullet proof solution :

您不喜欢正则表达式,但仍需要防弹解决方案:

function keep(o, keys) {
    for (var k in o) contains(keys, k) || delete o[k];
    return o;
}

function contains(array, value) {
    var i = -1, l = array.length;
    while (++i < l) if (array[i] === value) return true;
    return false;
}

function prefix(array, prefix) {
    var i = -1, l = array.length, output = [];
    while (++i < l) output.push(prefix + array[i]);
    return output;
}

Usage :

用法 :

keep(myObj, ['p1', 'p2', 'p100']);
// with a middleman :
var idsToKeep = [1, 2, 100];
keep(myObj, prefix(idsToKeep, 'p'));

Well, I could go on like this infinitely, but it's time to eat.

好吧,我可以无限地继续下去,但该吃饭了。

回答by leaf

An object stored in a variable named o:

存储在名为 的变量中的对象o

var o = { a: 1, b: 2 };

A new reference to this object :

对此对象的新引用:

var p = o;

oand pboth refer to the same object :

o并且p都指向同一个对象:

o // { a: 1, b: 2 }
p // { a: 1, b: 2 }
o === p // true

Let's update the object through o:

让我们通过o以下方式更新对象:

delete o.b;
o // { a: 1 }
p // { a: 1 }

Let's update the object through p:

让我们通过p以下方式更新对象:

p.b = 2;
o // { a: 1, b: 2 }
p // { a: 1, b: 2 }

As you can see, oand pare in sync.

如您所见,o并且p是同步的。



Let's "reinitialize" o:

让我们“重新初始化” o

o = { a: o.a };

oand pnow refer to different objects :

op现在引用不同的对象:

o // { a: 1 }
p // { a: 1, b: 2 }
o === p // false

Let's update the object stored in o:

让我们更新存储在 中的对象o

o.c = 3;
o // { a: 1, c: 3 }
p // { a: 1, b: 2 }

Let's update the object stored in p:

让我们更新存储在 中的对象p

delete p.a;
o // { a: 1, c: 3 }
p // { b: 2 }

As you can see, oand pare not in sync anymore.

正如你所看到的,op不同步了。



The question is : do you want to keep both variables (oand p) synchronized? If so, the second code block of VisioN's answeris the right one, otherwise, choose the first code block.

问题是:你想保持两个变量(op)同步吗?如果是,则VisioN 答案的第二个代码块是正确的,否则,选择第一个代码块。

回答by Soldeplata Saketos

You can code your own implementation of _.pick, and use it according to your needs.

您可以编写自己的 实现_.pick,并根据需要使用它。

Having this snippet of code as the base for the following cases:

将此代码片段作为以下情况的基础:

const myObj={
    p1:123,
    p2:321,
    p3:{p3_1:1231,p3_2:342},
    p4:'23423',
    //....
    p99:{p99_1:'sadf',p99_2:234},
    p100:3434
}
let properties= ['p1','p2', 'p3', 'p100'];

case 1:

情况1:

You want a shallow copy (with references to vector values)

你想要一个浅拷贝(引用向量值)

const myNewObj = properties.reduce((newObj,property)=>{newObj[property] = myObj[property]; return newObj}, {})
// if we modify the original vector value of 'p3' in `myObj` we will modify the copy as well:

myObj.p3.p3_1 = 99999999999;

console.log(myNewObj); // { p1: 123,??????????  p2: 321,??????????  p3: { p3_1: 99999999999, p3_2: 42 },??????????  p100: 3434 }?????

case 2:

案例2:

You want a deep copy (losing references to vector values)

你想要一个深拷贝(丢失对向量值的引用)

You can just use JSONutilities to that matter.

你可以只使用JSON实用程序来解决这个问题。

const myNewObj2 = properties.reduce((newObj,property)=>{newObj[property] = JSON.parse(JSON.stringify(myObj[property])); return newObj},{})

// no matter how hard you modify the original object, you will create a new independent object
myObj.p3.p3_1 = 99999999999;

console.log(myNewObj2) // { p1: 123, p2: 321, p3: { p3_1: 1231, p3_2: 342 }, p100: 3434 }?????

Reusing case 2 with a function

使用函数重用案例 2

You could implement a reducer to use it in different scenarios, like this one:

您可以实现一个减速器以在不同场景中使用它,例如:

function reduceSelectedProps(origin, properties){
  return (newObj,property)=>{
    newObj[property] = JSON.parse(JSON.stringify(origin[property]));
     return newObj
  }
}

So you could have a more elegant reuse of it:

所以你可以更优雅地重用它:

const myNewObj3 = properties.reduce(reduceSelectedProps(myObj, properties),{});
// no matter how hard you modify the original object, you will create a new independent object
myObj.p3.p3_1 = 99999999999;

console.log(myNewObj3) // { p1: 123, p2: 321, p3: { p3_1: 1231, p3_2: 342 }, p100: 3434 }?????

disclaimers:

免责声明:

This is only an example that does not handle Date, Set, Mapor functionvalues inside the properties. To deal with all these cases (and many others), it needs a really complex function with checks on the prototypes and all that stuff. At this point, consider reusing the work of other developers using any library that could do it. Lodash?

这仅仅是不处理的例子DateSetMapfunction特性内的值。为了处理所有这些情况(以及许多其他情况),它需要一个非常复杂的函数来检查原型和所有这些东西。此时,请考虑使用任何可以执行此操作的库来重用其他开发人员的工作。洛达什?

回答by user13592693

I Made this short solution for case where I have an array with objects.

我为我有一个包含对象的数组的情况制作了这个简短的解决方案。

so consider the array below?

所以考虑下面的数组?

arr=[{"a1":"A1","b1":"B1"},{"a1":"Z1","b1":"X1"}];
console.log(arr);

I want to keep only "b1" properties of all objects.

我只想保留所有对象的“b1”属性。

You can use map() and delete for that as follows:

您可以使用 map() 和 delete ,如下所示:

arr=[{"a1":"A1","b1":"B1"},{"a1":"Z1","b1":"X1"}];
arr=arr.map(function(d){
        delete d["a1"];
        return d;

    });
console.log(arr);

result is an array with objects but only "b1" properties.

结果是一个包含对象但只有“b1”属性的数组。

回答by GameAlchemist

You could create a view on your first object, some kind of proxy that would only keep the desired properties on sight.
For instance the following function will create a view that allows to both read and write the underlying object, keeping only the choosen properties.
You can make it readonly very easily, by just removing the setter.
You might also want to seal the proxy object, so that no later modification can me made to it.

你可以在你的第一个对象上创建一个视图,某种只能保持所需属性可见的代理。
例如,下面的函数将创建一个允许读写底层对象的视图,只保留选择的属性。
您可以非常轻松地将其设为只读,只需删除 setter。
您可能还想密封代理对象,以便我以后无法对其进行修改。

function createView(obj, propList) {
    var proxy = {};     
    for (var propIndex in propList) {    
         var prop=propList[propIndex];
         Object.defineProperty(proxy, prop, 
                {  enumerable : true , 
                   get : getter.bind(obj,prop), 
                   set : setter.bind(obj,prop)   } );

    }    
  return proxy;
}

function getter(prop) { return this[prop] ; }

function setter(prop, value) { return this[prop] = value ; }

An example of use would be :

一个使用示例是:

var myObj={
    p1:123,
    p2:321,
    p3:{p3_1:1231,p3_2:342},
    p4:'23423',
    p99:{p99_1:'sadf',p99_2:234},
    p100:3434
};

var objView = createView(myObj, ['p1', 'p2', 'p100']);

Here, objView 'reflects' the desired properties of myObj. You can look at the small jsbin i made here :

在这里,objView“反映”了 myObj 的所需属性。你可以看看我在这里制作的小 jsbin :

http://jsbin.com/munudewa/1/edit?js,console

http://jsbin.com/munudewa/1/edit?js,console

results :

结果 :

"on objView, p1:123 p2:321 p100:3434 and p4 (not in view) is : undefined"
"modifiying, on the view,  p1 to 1000 and p2 to hello "
"on objView, p1:1000 p2:hello p100:3434 and p4 (not in view) is : undefined"
"modifiying, on the viewed object,  p1 to 200 and p2 to bye "
"on objView, p1:200 p2:bye p100:3434 and p4 (not in view) is : undefined"

notice that :
1) you can overwrite an object by its view, only keeping desired properties.
2) you can save in a hidden property / in a closure, the original object, so you can later change the properties you expose.

请注意:
1)您可以通过其视图覆盖对象,仅保留所需的属性。
2)您可以将原始对象保存在隐藏属性/闭包中,以便以后可以更改公开的属性。

回答by Andy

I suppose you could add a new method to the prototype:

我想你可以在原型中添加一个新方法:

if (!('keepOnlyTheseProps' in Object.prototype)) {
  Object.prototype.keepOnlyTheseProps = function (arr) {
    var keys = Object.keys(this);
    for (var i = 0, l = keys.length; i < l; i++) {
      if (arr.indexOf(keys[i]) < 0) delete this[keys[i]];
    }
  }
}

myObj.keepOnlyTheseProps(['p1', 'p2', 'p100']);

Fiddle.

小提琴