0

i have an object coming from an API respone, looks like this:

{
  // ...
  customerName: 'Jake',
  customerUserName: 'jak3',
  customerEmail: 'some@email.com',
  // ...
}

and i want to declare a new object named apiUser to use in my app which sould look like this:

{
  name: 'Jake',
  userName: 'jak3',
  email: 'some@email.com'
}

i know i can do that using Object.assign() like this:

let apiUser = {};
Object.assign(apiUser, {
  name: response.customerName || 'John Doe', // customerName may be an empty string
  userName : response.customerUserName,
  email: response.customerEmail
});

Finally the question is: Can i do that by object destructuring? I've already tried:

let apiUser = {};
{customerName: apiUser.name, customerUserName: apiUser.userName, customerEmail: apiUser.email} = response;

but throwed and SyntaxError: Unexpected token : Is there any right syntax or should i stick with Object.assign()? And please don't forget the "John Doe" condition.

DonkeyKong
  • 746
  • 1
  • 9
  • 23
  • This often-requested feature does not exist in ES6. Although ES6 introduced new and improved object literal syntax, and of course destructuring into variables, and spread property syntax is moving through the standards progress, people seem very lukewarm toward destructuring into new objects. See https://esdiscuss.org/topic/picking-deconstructing-properties-into-object-literals. –  Aug 30 '17 at 13:19
  • i understand... For now i'll go with `Object.assign()`. Thanks! – DonkeyKong Aug 30 '17 at 13:25

4 Answers4

2

Why not just assign to a new variable, getting rid of the up-front assignment with let and then modifying the variable:

const apiUser = {
  name: response.customerName || 'John Doe',
  userName : response.customerUserName,
  email: response.customerEmail
};

Or if you want to add to the already existing fields:

const apiUser = Object.assign({}, originalObject, {
  name: response.customerName || 'John Doe',
  userName : response.customerUserName,
  email: response.customerEmail
}

This should also work:

const { customerName: name, customerUserName: userName, customerEmail: email } = originalObject;
const apiUser = {
  name,
  userName,
  customerEmail
};
Tobi Kremer
  • 487
  • 5
  • 18
  • Yes, you're right. Declaring and mutating the variable is unnecessary.. Your first example meets my requirement. I think i was eager to use object destructuring. – DonkeyKong Aug 30 '17 at 13:31
  • 1
    Hehe, I know that feeling. But most of the time, the straight-forward solution is the most readable. ;-) – Tobi Kremer Aug 30 '17 at 13:32
1

your final example is good you just need to wrap parens around the statement like this:

({customerName: apiUser.name, customerUserName: apiUser.userName, customerEmail: apiUser.email} = response)

however that wont let you do the conditional value. For that you would need to do Object.assign or one of the other methods you discussed.

EDIT

Turns out you can do the conditional value!

({customerName: apiUser.name = "John Doe", customerUserName: apiUser.userName, customerEmail: apiUser.email} = response)
Joseph Ditton
  • 658
  • 6
  • 7
0

It works as you'd expect:

let response = {
  // ...
  customerName: 'Jake',
  customerUserName: 'jak3',
  customerEmail: 'some@email.com',
  // ...
};


// Destructuring Assignment (w/ default value)
let apiUser = {};
({ customerName:     apiUser.name = 'John Doe', //<-- default value with '='
   customerUserName: apiUser.userName, 
   customerEmail:    apiUser.email
 } = response );


// Assign Prototype Method
/*
let apiUser = {};
Object.assign(apiUser, {
  name: response.customerName || 'John Doe', // customerName may be an empty string
  userName : response.customerUserName,
  email: response.customerEmail
});
*/

console.log(apiUser);

According to the MDN documentation of Assignment without declaration:

The ( .. ) around the assignment statement is required syntax when using object literal destructuring assignment without a declaration.

{a, b} = {a: 1, b: 2} is not valid stand-alone syntax, as the {a, b} on the left-hand side is considered a block and not an object literal.

However, ({a, b} = {a: 1, b: 2}) is valid, as is var {a, b} = {a: 1, b: 2}

NOTE: Your ( ..) expression needs to be preceded by a semicolon or it may be used to execute a function on the previous line.


Note: both Object.Assign and destructured assignment are by-and-large not available in Internet Explorer (Edge is a different story). Take that into consideration for your implementation.

BotNet
  • 2,259
  • 2
  • 13
  • 16
0

You could do something like:

let response = {
    CustomerName: '',
    CustomerUsername: 'jak3',
    CustomerEmail: 'some@email.com',
};
let apiUser = {
    Name: '',
    Username: '',
    Email: '',
};

(
    [
        apiUser.Name,
        apiUser.Username,
        apiUser.Email
    ] = [
        response.CustomerName || 'John Doe',
        response.CustomerUsername,
        response.CustomerEmail
    ]
);
console.log(apiUser);

However I am not sure how is that an improvement in readability as compared to not using any fancy feature and instead just doing:

let response = {
    CustomerName: '',
    CustomerUsername: 'jak3',
    CustomerEmail: 'some@email.com',
};
let apiUser = {
    Name: response.CustomerName || 'John Doe',
    Username: response.CustomerUsername,
    Email: response.CustomerEmail,
};
console.log(apiUser);

Surely this is easier to read and understand? Is there any specific reason why you are trying to use a more esoteric syntax to achieve this?

Richard Knop
  • 73,317
  • 142
  • 374
  • 539
  • i'm new to es6 and i wanted to use one of it's new features. I thought i could use object destructuring but end up feeling like "using a feature just to use it". – DonkeyKong Aug 30 '17 at 13:49
  • I agree with Richard, some of the new syntax is just too difficult to comprehend because it doesn't make logical sense. This is especially true of the object destructuring, which requires a backwards-syntax of value/property from typical object constructing. – BotNet Aug 30 '17 at 14:01