5

This is how I've been doing it:

var props = { id: 1, name: 'test', children: [] }

//copy props but leave children out
var newProps = { ...props }
delete newProps.children

console.log(newProps) // { id: 1, name: 'test' }

Is there a cleaner, simpler way?

Evan Hobbs
  • 3,231
  • 5
  • 26
  • 37
  • I don't understand. You haven't write the most important line, where you copy props to newProps. What's "..."? – Gavriel Jan 28 '16 at 21:59
  • @william.taylor.09, not duplicate. He knows how to copy (he just haven't show that line) but he want's to copy all properties except some in a blacklist – Gavriel Jan 28 '16 at 22:01
  • @Gavriel doesn't this line basically shallow copy the properties the new object `var newProps = { ...props }`? Sort of like doing `var newProps = Object.assign({}, props)` – Evan Hobbs Jan 28 '16 at 22:06
  • It gives me error: "Uncaught SyntaxError: Unexpected token". I don't understand, you said: "This is how I've been doing it", I thought you have a working version, and are looking for a nicer way to do it. However I posted one possible way below – Gavriel Jan 28 '16 at 22:09
  • @Gavriel it's a spread operator: http://babeljs.io/repl/#?experimental=false&evaluate=false&loose=false&spec=false&code=a%3D%7B...b%7D – Tamas Hegedus Jan 28 '16 at 22:18
  • ah, I missed the babeljs tag, sebaj :) – Gavriel Jan 28 '16 at 22:21
  • 1
    @Bergi, it's not a duplicate. The other question is the complementer of this one: there he wants to copy according to a white-list, and here according to a black-list – Gavriel Jan 28 '16 at 23:16
  • @Gavriel: Ah, right, though a whitelist is definitely cleaner. – Bergi Jan 28 '16 at 23:46
  • I would say more secure, but cleaner depends on many things. If I have 20 properties and I don't want 2 of them, then blacklist will surely be cleaner or more readable – Gavriel Jan 28 '16 at 23:49

2 Answers2

10

You could use a destructuring assignment:

var props = { id: 1, name: 'test', children: [] }

var {children:_, ...newProps} = props;
console.log(newProps) // { id: 1, name: 'test' }
console.log(_) // [] - as an "empty" placeholder

(with the same rest/spread properties proposal for ES7 that you were already using)

icc97
  • 8,746
  • 6
  • 60
  • 75
Bergi
  • 513,640
  • 108
  • 821
  • 1,164
  • Yeah I think this is the best option - I was doing something similar before. I just wish there was something more explicit... – Evan Hobbs Jan 29 '16 at 17:56
  • I think it's pretty explicit already… If want, you can write an aptly named function `(key, {[key]:_, ...rest}) => rest` and call that. – Bergi Jan 29 '16 at 23:27
  • 1
    `/* eslint no-unused-vars: ["error", { "varsIgnorePattern": "_"] */` Is useful to get rid of eslint errors when using this technique – icc97 May 13 '17 at 23:39
  • Thanks for the answer. This helped. But I should agree with @EvanHobbs - I would've expected to have a much more intuitive way to do this. – nikjohn Nov 02 '17 at 15:27
1

var props = { id: 1, name: 'test', children: [] }

function clone(orig, blacklistedProps) {
    var newProps = {};
    Object.keys(props).forEach(function(key) {
        if (!blacklistedProps || blacklistedProps.indexOf(key) == -1) {
            newProps[key] = props[key];
        }
    });
    return newProps;
}
var newProps = clone(props, ['children']); 
console.log(newProps) // { id: 1, name: 'test' }
var newProps1 = clone(props); 
console.log(newProps1) // { id: 1, name: 'test', children:[] }
Gavriel
  • 18,088
  • 12
  • 63
  • 98
  • Thanks @gavriel. Yeah for that matter I guess I could wrap my logic in a clone function. I was just hoping there was a more concise way. – Evan Hobbs Jan 28 '16 at 23:13