我有一个对象。我想通过删除除某些特定属性之外的所有属性来修改对象(而不是克隆它)。例如,如果我开始使用这个对象:
var myObj={
p1:123,
p2:321,
p3:{p3_1:1231,p3_2:342},
p4:'23423',
//....
p99:{p99_1:'sadf',p99_2:234},
p100:3434
}
并且只想要属性p1,p2和p100,我该如何获得这个对象:
var myObj={
p1:123,
p2:321,
p100:3434
}
我理解如何用蛮力做到这一点,但想要更优雅的解决方案。
答案 0 :(得分:6)
重新初始化对象:
myObj = {
p1: myObj.p1,
p2: myObj.p2,
p100: myObj.p100
};
另一种方法是删除某些效果较差的属性:
var prop = ['p1', 'p2', 'p100'];
for (var k in myObj) {
if (prop.indexOf(k) < 0) {
delete myObj[k];
}
}
答案 1 :(得分:6)
这是谷歌搜索'js仅保留某些键'时的第一次点击,因此可能值得更新。
最“优雅”的解决方案可能就是使用underscore.js
_.pick(myObj, 'p1', 'p2', 'p100')
答案 2 :(得分:3)
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);
答案 3 :(得分:3)
您可以使用delete
:
for (var k in myObj) {
if (k !== 'p1' && k !== 'p2' && k !== 'p100') {
delete myObj[k];
}
}
indexOf
的替代方案:
var keep = /^p(1|2|100)$/;
for (var k in myObj) {
if (!keep.test(k)) {
delete myObj[k];
}
}
更短:
var keep = /^p(1|2|100)$/;
for (var k in myObj) {
keep.test(k) || delete myObj[k];
}
RegExp数组:
var keep = [1, 2, 100];
keep = new RegExp('^p(' + keep.join('|') + ')$'); // /^p(1|2|100)$/
keep.test('p1'); // true
keep.test('p3'); // false
对函数有用:
function keep(o, ids) {
var keep = new RegExp('^p(' + ids.join('|') + ')$');
for (var k in o) keep.test(k) || delete o[k];
return o;
}
用法:
keep(myObj, [1, 2, 100]); // { p1: 123, p2: 321, p100: 3434 }
您不喜欢正则表达式,但仍需要防弹解决方案:
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;
}
用法:
keep(myObj, ['p1', 'p2', 'p100']);
// with a middleman :
var idsToKeep = [1, 2, 100];
keep(myObj, prefix(idsToKeep, 'p'));
好吧,我可以无限地继续这样做,但现在是时候吃了。
答案 4 :(得分:3)
Lodash有一个名为pick
的函数可以完成您所描述的内容。我知道包含一个库并不理想,但你也可以在使用bundle等时选择函数。
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')
答案 5 :(得分:1)
存储在名为o
的变量中的对象:
var o = { a: 1, b: 2 };
对此对象的新引用:
var p = o;
o
和p
都指向同一个对象:
o // { a: 1, b: 2 }
p // { a: 1, b: 2 }
o === p // true
让我们通过o
更新对象:
delete o.b;
o // { a: 1 }
p // { a: 1 }
让我们通过p
更新对象:
p.b = 2;
o // { a: 1, b: 2 }
p // { a: 1, b: 2 }
如您所见,o
和p
是同步的。
让我们“重新初始化”o
:
o = { a: o.a };
o
和p
现在引用不同的对象:
o // { a: 1 }
p // { a: 1, b: 2 }
o === p // false
让我们更新o
中存储的对象:
o.c = 3;
o // { a: 1, c: 3 }
p // { a: 1, b: 2 }
让我们更新p
中存储的对象:
delete p.a;
o // { a: 1, c: 3 }
p // { b: 2 }
如您所见,o
和p
不再同步。
问题是:您是否要同时保持两个变量(o
和p
)?如果是,则VisioN's answer的第二个代码块是正确的,否则,选择第一个代码块。
答案 6 :(得分:1)
您可以使用这种方法:
let result = (({ p1, p2, p100 }) => ({ p1, p2, p100 }))(myObj);
答案 7 :(得分:0)
您可以在第一个对象上创建一个视图,某种代理只能保持所需的属性 例如,以下函数将创建一个允许读取和写入底层对象的视图,仅保留选择的属性 只需移除设定器,即可轻松实现只读 您可能还想密封代理对象,以便以后不再对其进行修改。
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 ; }
使用的一个例子是:
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']);
这里,objView'反映'myObj的所需属性。 你可以看看我在这里制作的小jsbin:
http://jsbin.com/munudewa/1/edit?js,console
结果:
"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"
注意:
1)您可以通过视图覆盖对象,只保留所需的属性
2)您可以将原始对象保存在隐藏属性/闭包中,以便稍后更改您公开的属性。
答案 8 :(得分:0)
我想你可以为原型添加一个新方法:
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']);
答案 9 :(得分:0)
将列入白名单的密钥映射到IIFE(立即调用的函数表达式);不仅仅是优雅而且灵活的IMO(特别是如果转移到与Juan Mendes的回答不同的功能)
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 myObj = (function(origObj, whiteListMap) {
for (var prop in origObj) {
if (!whiteListMap[prop]) {
delete origObj[prop];
}
}
return myObj;
})(myObj, {'p1': 1, 'p2': 1, 'p100': 1});
console.log(JSON.stringify(myObj)); //{"p1":123,"p2":321,"p100":3434}
答案 10 :(得分:0)
您可以编写自己的_.pick
实施代码,并根据您的需要使用它。
将以下代码段作为以下情况的基础:
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'];
您需要浅层副本(引用向量值)
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 }
您需要深层复制(失去对矢量值的引用)
您可以使用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 }
你可以实现一个reducer在不同的场景中使用它,比如这个:
function reduceSelectedProps(origin, properties){
return (newObj,property)=>{
newObj[property] = JSON.parse(JSON.stringify(origin[property]));
return newObj
}
}
所以你可以更优雅地重复使用它:
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 }
<强>免责声明:强>
这只是一个不处理属性中Date
,Set
,Map
或function
值的示例。为了处理所有这些情况(以及许多其他情况),它需要一个非常复杂的功能,检查原型和所有这些东西。此时,请考虑重复使用任何可以执行此操作的库的其他开发人员的工作。 Lodash?
答案 11 :(得分:0)
对于有对象数组的情况,我做了简短的解决方案。
所以考虑下面的数组吗?
arr=[{"a1":"A1","b1":"B1"},{"a1":"Z1","b1":"X1"}];
console.log(arr);
我只希望保留所有对象的“ b1”属性。
您可以使用map()并将其删除,如下所示:
arr=[{"a1":"A1","b1":"B1"},{"a1":"Z1","b1":"X1"}];
arr=arr.map(function(d){
delete d["a1"];
return d;
});
console.log(arr);
结果是一个包含对象但只有“ b1”属性的数组。