2016-01-09 51 views
78

我有一个平坦的JS对象:克隆一个JS对象除了一键

{a: 1, b: 2, c: 3, ..., z:26} 

我要克隆的对象,除了一个元素:

{a: 1, c: 3, ..., z:26} 

怎样做最简单的方法(如果可能,宁愿使用es6/7)?

回答

131

如果使用Babel你可以用下面的语法来从x转换成变量b复制属性b,然后性质的其余部分复制到变量y

let x = {a: 1, b: 2, c: 3, z:26}; 
let {b, ...y} = x; 

it will be transpiled成:

"use strict"; 

function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } 

var x = { a: 1, b: 2, c: 3, z: 26 }; 
var b = x.b; 

var y = _objectWithoutProperties(x, ["b"]); 
+8

如果你为未使用的变量提供你的代码,这将导致“未使用的变量b”。警告虽然。 –

+0

如果您有'let x = [{a:1,b:2,c:3,z:26},{a:5,b:6,c:7,z:455}],语法如何? ;' – ke3pup

+0

你可以使用[Array.prototype.map()](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/map)作为数组。 ''let y = x.map(item => {/ *从项中移除一个键并返回它* /})''' –

5

也许是这样的:

var copy = Object.assign({}, {a: 1, b: 2, c: 3}) 
delete copy.c; 

这是不够好?或者不能c实际上被复制?

+0

只是几乎没有打到拳打。 – dardub

34
var clone = Object.assign({}, {a: 1, b: 2, c: 3}); 
delete clone.b; 

,或者如果你接受被未定义的属性:

var clone = Object.assign({}, {a: 1, b: 2, c: 3}, {b: undefined}); 
+2

简单地删除该属性是一个清晰而简单的方法。 – sshow

+4

删除的警告是它不是不可变的操作。 –

+0

这会保留密钥 –

12

您可以编写一个简单的辅助功能吧。 Lodash具有相同名称的类似功能:omit

function omit(obj, omitKey) { 
    return Object.keys(obj).reduce((result, key) => { 
    if(key !== omitKey) { 
     result[key] = obj[key]; 
    } 
    return result; 
    }, {}); 
} 

omit({a: 1, b: 2, c: 3}, 'c') // {a: 1, b: 2} 

另外,还要注意它比Object.assign更快,然后将其删除:http://jsperf.com/omit-key

26

要添加到伊利亚Palkin的回答是:你甚至可以动态删除键:

const x = {a: 1, b: 2, c: 3, z:26}; 

const objectWithoutKey = (object, key) => { 
    const {[key]: deletedKey, ...otherKeys} = object; 
    return otherKeys; 
} 

console.log(objectWithoutKey(x, 'b')); // {a: 1, c: 3, z:26} 
console.log(x); // {a: 1, b: 2, c: 3, z:26}; 

Demo in Babel REPL

来源:

+0

'[key]:deletedKey'事物非常好,因为它适用于保留关键字,例如: 'let {['for']:deletedKey, ... otherKeys} = {a:1,b:2,for:10}' '// otherKeys = {a:1,b:2} =>没有更多的'key' 我正在使用它使用React/JSX和TypeScript –

+0

这是一个很好的语法。 – Hinrich

+0

这很好,但有没有办法避免未使用的var deletedKey?并不是说它造成了任何问题,而是让JSHint抱怨,而且看起来很奇怪,因为我们真的没有使用它。 –

24

对于那些不能使用ES6的人,可以使用lodashunderscore

_.omit(x, 'b') 

ramda

R.omit('b', x) 
+4

在这里使用[omit](https://lodash.com/docs/4.17.4#omit)更合乎逻辑吗? '_.omit(x,'b')' – tibalt

+0

Thanks @tibalt。用它更新了答案。 – dashmug

1

如果你正在处理一个巨大的变量,你不希望复制它,然后将其删除,因为这将是低效的。

一个简单的for循环使用hasOwnProperty检查应该工作,它更适应未来的需求:

for(var key in someObject) { 
     if(someObject.hasOwnProperty(key) && key != 'undesiredkey') { 
       copyOfObject[key] = someObject[key]; 
     } 
} 
1

Lodash omit

let source = //{a: 1, b: 2, c: 3, ..., z:26} 
let copySansProperty = _.omit(source, 'b'); 
// {a: 1, c: 3, ..., z:26} 
0

如果你打算使用lodash我建议你使用.omit这是一种简单的方法来创建一个对象组成一个现有的对象属性,除了你选择的对象属性,问题是,它是在文档中描述的慢于.pick,所以你m唉在使用前三思而后行

var object = {a: 1, b: 2, c: 3, ..., z:26}; // your object 
_.pick(object, ['b']); 
// => { 'a': 1, 'c': 3, ..., z:26 }