Refactoring a destructuring into an object destructuring - javascript

I am refactoring my code, which involves converting a big list of let statements into an object called personDetails:
personDetails = {
firstName: '',
lastName: '',
zipcode: 'xyz',
age: 20,
gender: 'm'
}
Currently, I am destructuring the values returned from my array like this:
[firstName, lastName] = getNames(zipcode, age, gender)
This works fine. But now that I am switching to an object, how do I update that object with the returned values? I will be passing in the object as an argument like this:
getNames(personDetails)
Do I have to do something like this?
personDetails = getNames(personDetails)
The called function might look something like this (abbreviated):
const getNames(personDetails) => {
personDetails.firstname = 'Jack'
personDetails.lastName = 'Jones'
}

1) Your arrow function had a typo, you must declare it with an = before the argument, like this:
const getNames = (personDetails) => { // Correct
const getNames(personDetails) => { // Incorrect
2) Inside your function, you weren't modifying an object key, but creating a new one instead. Remember that objects keys differs if you use upper or lowercase letters, firstName and firstname are not the same key.
3) Last, when you create an argument in your function, do not declare it with the same name of the global object, since it could create unexpected results. Then, you don´t need to destructure your object, just return the complete object.
let personDetails = { // Using let
firstName: '',
lastName: '',
zipcode: 'xyz',
age: 20,
gender: 'm'
};
const getNames = (obj) => { // obj is the argument
obj.firstName = 'Jack';
obj.lastName = 'Jones';
return obj; // Return complete object
}
personDetails = getNames(personDetails);
console.log(personDetails);
If you want to destructure the object, you can do it too the same way you do it with the array, but I wouldn´t recommend it because it makes the code less clear:
const personDetails = { // Using const
firstName: '',
lastName: '',
zipcode: 'xyz',
age: 20,
gender: 'm'
};
const getNames = (obj) => { // obj is the argument
obj.firstName = 'Jack';
obj.lastName = 'Jones';
return [obj.firstName, obj.lastName]; // Return part of object as an array
}
[personDetails.firstName, personDetails.lastName] = getNames(personDetails);
console.log(personDetails);

Related

TypeScript: Why is the same object cannot be assigned with the interface when defined but can be assigned when passed as a parameter

Here I have a object and an interface, its shape is like this
interface OBJ {
firstName: string;
lastName: string;
}
const obj: OBJ = { firstName: "John", lastName: "Smith", random: 1 };
Here clearly TS compiler would error on 'random' does not exist in type 'OBJ'.
However if I have a function as this
const getNewObj = (obj: OBJ) => ({
fullName: obj.firstName + obj.lastName,
...obj
});
then I pass obj into this function
console.log(getNewObj(obj));
There is no error. How come?
Live demo: https://codesandbox.io/s/eager-joliot-s4j93?file=/src/index.ts:289-318
TypeScript has this Strict object literal checking. simply put for functions: if you pass an object reference (variable or constant) to the function, typescript will check if this object reference contains the keys required for your function. Nothing less, but will allow from more keys.
Example of this:
const getNewObj = (obj: OBJ) => ({
fullName: obj.firstName + obj.lastName,
...obj
});
const obj1 = {firstName: "John", lastName: "Smith", random: 1}
const obj2 = {lastName: "Smith", random: 1}
getNewObj(obj1); // This is good, eventhough property random is extra
getNewObj(obj2); // Error: property firstName is missing
On the other hand, if you pass your function an object (not an object reference), then typescript will type check that object and throws an error for missing and extra properties
Example, with the same function:
getNewObj({ firstName: "John", lastName: "Smith" }) // good
getNewObj({ firstName: "John", lastName: "Smith", random: 1 }) //'random' does not exist..
getNewObj({ lastName: "Smith" }) // Property 'firstName' is missing...
More detail on this Strict object literal can be found in this gitbook

JavaScript - Exporting a harcoded array vs creating one

Let's say I have a file data.js, which contains an array of some data that will be imported somewhere (eg. a React component).
EXAMPLE A:
const DATA = [
{
firstName: 'jim',
lastName: 'beam',
fullName: 'jim beam'
},
{
firstName: 'jack',
lastName: 'daniels',
fullName: 'jack daniels'
}
];
export default DATA;
Ok, cool. Thing is, we're writing out the fullName property, which could be gathered by combining firstName and lastName. This is a very trivial example for clarity, so bear with me. We could also do something like this:
EXAMPLE B:
const DATA = [
{ firstName: 'jim', lastName: 'beam' },
{ firstName: 'jack', lastName: 'daniels' }
];
export default DATA.map(person => ({
...person,
fullName: `${person.firstName} ${person.lastName}`
});
Heck, we could even do this!
EXAMPLE C:
const DATA = ['jim beam', 'jack daniels'];
export default DATA.map(person => {
const [firstName, lastName] = person.split(' ');
return {
firstName,
lastName,
fullName: person
};
};
So, imagine you have a huuge list of data, where multiple values could be derived from one initial value. My question is how would examples B and C differ from just hardcoding everything right off the bat like example A?
If you had hundreds of items, examples B and C could have much less overhead, a smaller file size, and can reduce potential typos... But, we're declaring an array and then exporting a different one, which I assume could have a performance dip? Thoughts?
How about a class with a getter that evaluates fullName on access?
It offers smaller in-memory size, and doesn't have a performance issue because fullName property of each datum is not computed until they are imported, and accessed.
class Person {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
get fullName() {
return `${this.firstName} ${this.lastName}`
}
}
let a = new Person('Charles', 'Martel');
console.log(a.fullName)
// expected result: "Charles Martel"
Your data can then be declared as the following.
const DATA = [
new Person('jim', 'beam'),
new Person('jack','daniels')
];

Object Destructuring ignoring values

I'm trying to destructure and ignore few values, how do I do that?
For example:
const test = { name: 'John', age: 29, gender: 'male'}
function getData(...args) {
const {,,gender} = args[0];
console.log(gender); // should print male.
}
getData(test);
I want to ignore (not declare variables for) name and age parameters (so that my ESLint does not throw an error) at the same time use ES6.
The syntax , does not seem to work either. Any other workarounds for this problem?
You have a single arg (the object), and you should object destructuring to get gender:
const test = { name: 'John', age: 29, gender: 'male'}
function getData(arg) {
const { gender} = arg;
console.log(gender); // should print male.
}
getData(test);

How to populate an array in javascript if I want to have multiple elements for a single index of an array

How to populate an array in javascript when I want to store multiple elements in a single index?
I want to populate an array in Javascript. What I am trying to do is to store both firstName and lastName of a person in an array index. I am trying to do person[0].firstName = 'Dilshadur'; and then person[0].secondName = 'Rahman'; but It's not working and I think this is not the correct syntax to do so.
person[0].firstName.fill('Md Dilshadur Rahman');
person[0].lastName = 'Rahman';
person[1].firstName = 'Tabassum Monia';
person[1].lastName = 'Disha';
I am getting in the console something like this: "Uncaught TypeError: Cannot read property 'firstName'", I think this because of the wrong syntax and I am not being able to find the correct syntax.
You would have to have an object assigned to each index of the array, and each of those objects would have the firstName and lastName properties.
Ex:
let person = [];
person[0] = {firstName: 'Dilshadur', lastName: 'Rahman'};
person[1] = {firstName: 'Tabassum Monia', lastName: 'Disha'};
You should consider creating a separate class or something where this structure is defined.
class Person {
constructor(first, last) {
this.firstName = first;
this.lastName = last;
}
}
let person = [];
person[0] = new Person('Dilshadur', 'Rahman');
person[1] = new Person('Tabassum Monia', 'Disha');
You need to store an array of objects in that case.
const results = [
{ firstName: 'clark', lastName: 'kent' },
{ firstName: 'bruce', lastName: 'wayne' }
]
You can then use the spread operator to populate the entire index.
const newResults = [
{ firstName: 'peter', lastName: 'parker' },
...results
]
You can also push to your array, however it is good practice to not mutate your data and instead create an updated copy of it.
You can create array of objects
person = [];
person[0] = { firstName: "abc" , lastName: "def" } :
Or you can push values to it by
person.push( { firstName: "abc" , lastName: "def" } )

ES6 object namespacing

I came across some syntax I haven't seen before. When I deal with objects and when using React, you can simplify namespacing by doing such as
let {someProp} = prevProps
Doing this allows me to avoid writing prevProps.someProp everytime I want to use it.
What I don't understand is this syntax
let {someProp: oldData} = prevProps
console.log(someProp) will show the value of the prevPros.someProp but WHERE does oldData come from???
console.log(olddata) above this line will show undefined but console.log(oldData) underneath will show the previous props.
let {someProp: myAlias} = prevProps
This syntax allows you use an alias, for example you can use myAlias in your code, instead someProp, it is called Object destructuring
As stated in the comments by #FelixKling here is the official reference.
Example from provided link:
let o = {p: 42, q: true};
let {p: foo, q: bar} = o;
console.log(foo); // 42
console.log(bar); // true
Yes:
let {someProp} = prevProps
is similar to this:
let someProp = prevProps.someProp;
And this:
let {someProp: oldData} = prevProps
would be similar to this:
let oldData = prevProps.someProp
Take a look at this link
Basically you are destructuring prevProps and in this case oldData will now be have the value of someProp
This syntax is one of the shiny new things in ES6 called object destructuring.
Here's an elaborate example on how you can use destructuring in different ways
const person = {
first: 'Jack',
last: 'Daniels',
address: {
city: 'Dallas',
}
};
// destructure as it is
const { first, last } = person;
// destructure with custom name
const { first: firstName, last: lastName } = person;
// destructure with default value
const { first, last, middle = 'The Boss' } = person;
// destructure with custom name and default value
const { first, last, middle: middleName = 'The Boss' } = person;
// destructure nested keys
const { first, last, address: { city } } = person;
// destructure nested keys with custom name
const { first, last, address: { city: myCity } } = person;
// destructure nested keys safely
const { first, last, address: { city } = {} } = person;
// destructure rest of the values
const { first, ...rest } = person; // => rest will have all keys but first

Categories

Resources