0

I am trying to find a way so that I can remove the repetitive need for having to use the object name and just the keys. For example:

function(teams) {
    return {
        teamName: teams.name,
        teamCity: teams.city,
        teamState: teams.state,
        teamMascot: teams.mascot
    }
}

It would be nice so that I can have it so that the need to re-use teams each time can be eliminated. Any help would be great.

Mike Cluck
  • 31,869
  • 13
  • 80
  • 91
pertrai1
  • 4,146
  • 11
  • 46
  • 71
  • Why do you want to do this? What's wrong with using the original object with property names like `name`? –  Oct 21 '16 at 19:36

4 Answers4

1

Something like this?

function (teams) {
    const {name, city, state, mascot} = teams;
    return {
        teamName: team,
        teamCity: city,
        teamState: state,
        teamMascot: mascot
    }
}
Ramiz Wachtler
  • 5,623
  • 2
  • 28
  • 33
1

You've already mentioned the solution in your title. Just use destructuring.

function logTeam(teams) {
  let { name, city, state, mascot } = teams;
  console.log({
    teamName: name,
    teamCity: city,
    teamState: state,
    teamMascot: mascot
  });
}

logTeam({
  name: 'SO Silverhawks',
  city: 'Interwebs',
  state: 'Earth',
  mascot: 'Stacky'
});

If you want to avoid using the names at all but your properties follow a predictable pattern, you can use Object.keys and work with the keys directly.

function capitalizeFirstLetter(string) {
  return string.charAt(0).toUpperCase() + string.slice(1);
}

function createTeam(teams) {
  let result = {};
  Object.keys(teams).forEach(key => {
    result[`team${capitalizeFirstLetter(key)}`] = teams[key];
  });
  return result;
}

console.log(createTeam({
  name: 'SO Silverhawks',
  city: 'Interwebs',
  state: 'Earth',
  mascot: 'Stacky'
}));

capitalizeFirstLetter source

Community
  • 1
  • 1
Mike Cluck
  • 31,869
  • 13
  • 80
  • 91
  • What about if I have lots of keys? Do I have to add all of them? Tried to use `...rest` but did not work the way I tried. – pertrai1 Oct 21 '16 at 19:15
  • Which eliminates the need to dereference teams over and over, but now each field name must be referenced twice, so I'm not sure this really gains anything, personally. – Dogs Oct 21 '16 at 19:15
  • 1
    @pertrai1 Yes, if that's how you want to do it. If the properties you're assigning to will always be `team${TitleCaseObjectKey}` then there's a solution for that as well. – Mike Cluck Oct 21 '16 at 19:16
  • @MikeC Yes it would be great to do it in a way where I don't have to list every one of them as there are close to 20 keys. They don't all start the same so I can't use the option you showed. So should `let { name, city, state, mascot, ...more} = teams` work or am I doing that wrong? – pertrai1 Oct 21 '16 at 19:20
  • @MikeC I was told it is best to factor out the object into a variable so it does not have to be duplicated so much but that does not click for me. – pertrai1 Oct 21 '16 at 19:22
  • @pertrai1 You're doing that wrong. The rest/spread operator (`...more`) is for arrays. Theoretically, doing `let { name, city, ...more } = teams` would put the remaining keys into an array named `more`. You can't dynamically create variables in the current scope without some serious bad idea tom-foolery. – Mike Cluck Oct 21 '16 at 19:22
  • @pertrai1 Extracting properties from an object into a variable is only really a good idea if you're planning to reference that same property multiple times. Every time you grab a property from an object, some kind of lookup occurs. The engine can optimize this in some cases but it can't in the general case. It can be helpful for reading comprehension to separate them out but that's a judgement call based on the context of the function and how many variables you're generating. – Mike Cluck Oct 21 '16 at 19:24
  • @MikeC Thank you so much for the help and explanations – pertrai1 Oct 21 '16 at 19:25
  • @pertrai1 Any time. Glad I could help! – Mike Cluck Oct 21 '16 at 19:25
1

The most straightforward approach, given the inability to destructure into objects, is:

const getTeamData = 
  ({name: teamName, city: teamCity, state: teamState, mascot: teamMascot}) =>
    ({teamName, teamCity, teamState, teamMascot});

Various approaches have been suggested for destructuring into objects, which would allow the following kind of syntax:

function getTeamData(team) {
  return team.{name: teamName, city: teamCity, state: teamState, mascot: teamMascot};
}

or

function getTeamData(team) {
  return { {name: teamName, city: teamCity, state: teamState, mascot: teamMascot} = team };
}

But the powers that be on TC39 have shown no interest in such alternatives.

Proxies

Alternatively, since all you seem to want to be doing is to access the name field as teamName, consider using a proxy:

function getTeamData(team) {
  return new Proxy(team, {
    get(target, prop) { return target[`team${capitalize(prop)}`]; }
  });
}
1

If you have an object with many properties, you can use this function that loops over them:

function prefix(obj, prefix) {
    return Object.keys(obj).reduce( (o, k) => 
        Object.assign(o, { [prefix+k.charAt(0).toUpperCase()+k.substr(1)]: obj[k]} ),
        {} );
}

var result = prefix({
    name: '49ers',
    city: 'San Francisco',
    state: 'California',
    mascot: 'Sourdough Sam'
}, 'team');

console.log(result);
trincot
  • 317,000
  • 35
  • 244
  • 286
  • With all due respect, this seems like a complicated solution to a problem which doesn't exist. –  Oct 21 '16 at 19:37
  • It is just an answer to address an apparent need the OP expressed in a comment to another answer: *"What about if I have lots of keys? Do I have to add all of them?"*. But I like how you have approached it in your answer. – trincot Oct 21 '16 at 19:46
  • Or `return Object.assign({}, ...Object.keys(obj).map(k => ({[prefix+k.charAt(0).toUpperCase()+k.substr(1)]: obj[k]}));`. –  Oct 21 '16 at 19:51