JavaScript delete operator and Object.create() method - javascript

I am trying to remove a property from an Person object like this:
const Person = {
firstname: 'John',
lastname: 'Doe'
}
console.log(Person.firstname);
// Output: "John"
delete Person.firstname;
console.log(Person.firstname);
// Output: undefined
When I am using this delete operator is working fine and Person.firstname log is showing as undefined as expected. But when I create a new object using this Person object using Object.create() method like this:
const Person = {
firstname: 'John',
lastname: 'Doe'
}
const Person2 = Object.create(Person);
console.log(Person2.firstname);
// Output: "John"
delete Person2.firstname;
console.log(Person2.firstname);
// expected output: undefined
// actual output: "John"
You can see Person2.firstname is returning "John" in the end, when I was expecting it to work same way as done in the first snippet and return undefined.
So, my questions here are:
Why is delete Person2.firstname not working?
Also, how can we delete firstname property from the Person2 object?
Thanks for your help.

delete will only successfully remove a property from an object if the property to be deleted is an own non-configurable property. Here, your Person2 does not have an own property of firstname, so delete Person2.firstname doesn't work. The property exists on the internal prototype of Person2, but not on Person2 itself.
To delete the property, you'll have to call delete with the prototype object:
delete Person.firstname;
const Person = {
firstname: 'John',
lastname: 'Doe'
}
const Person2 = Object.create(Person);
delete Person.firstname;
console.log(Person2);
or, if you don't already have a reference to it, use Object.getPrototypeOf:
delete Object.getPrototypeOf(Person2).firstname;
const Person = {
firstname: 'John',
lastname: 'Doe'
}
const Person2 = Object.create(Person);
delete Object.getPrototypeOf(Person2).firstname;
console.log(Person2);

you are creating a shallow copy and you want to do deep copy
tht can be achieved by something like
const Person = {
firstname: 'John',
lastname: 'Doe'
}
const Person2 = Object.assign({},Person);
console.log(Person2.firstname);
// Output: "John"
delete Person2.firstname;
console.log(Person2.firstname);
// expected output: undefined
// actual output: "undefined"
console.log(Person2.lastname)
this will give you more clarity on shallow and deep copy

Related

Should I deep copy when modifying nested object?

I recently started learning functional programming in Javascript, and one thing that's valued is Immutability. One way to preserve immutability is to when we want to modify some object that we first create a copy and then modify that copy and return it, for example:
const person = {
firstName: 'John',
lastName: 'Smith',
}
const modifyFName = obj => {
const objCopy = {...obj};
objCopy.firstName = 'James';
return objCopy;
}
console.log(modifyFName(person)) // {firstName: 'James', lastName: 'Smith'}
console.log(person) // {firstName: 'John', lastName: 'Smith'}
But if I want to modify some deeply nested object creating shallow copy like one above wouldn't make much of a difference, for example:
const person = {
firstName: 'John',
lastName: 'Smith',
parents: {
mom: {
firstName: 'Jennifer',
lastName: "Swift"
},
dad: {
firstName: 'Tom',
lastName: 'Cartman'
}
}
}
const modifyDadName = obj => {
const objCopy = {...obj};
objCopy.parents.dad.firstName = 'Aurelion';
return objCopy;
}
console.log(modifyDadName(person)) // {... dad: "Aurelion"}
console.log(person) // {... dad: "Aurelion"}
Both objects have changed. So I am wondering in this situation should I perhaps use deep copy, or maybe use some third-party Immutable data structures, or is there some other solution for this?
You're right that a shallow copy doesn't help, but you don't need a full deep copy, you only have to make copies of the things you want to change. In your case, that's person, parents, and dad, but not mom:
const modifyDadName = obj => {
return { // Replacement `obj` (`person`)
...obj,
parents: { // Replacement `obj.parents`
...obj.parents,
dad: { // Replacement `obj.parents.dad`
...obj.parents.dad,
firstName: "Aurelion", // New name
}
}
};
};
dad changes because, well, that's the operation we're doing (changing firstName). :-) parents changes because changing dad means there's a new object on its dad property. person (obj) changes because there's a new parents object. But mom doesn't change, so we can reuse the same object.

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

Destructure object and assign to another object in one line [duplicate]

This question already has answers here:
Is it possible to destructure onto an existing object? (Javascript ES6)
(16 answers)
Closed 2 years ago.
Is there a way to do the following in one line?
let person = {}
const { firstName, lastName } = getNames()
//or this
//const { firstName, lastName } = await getNames()
person.firstName = firstName
person.lastName = lastName
I often do this when coding, and hoping there is a shortcut. I can not see any hints on how to do this on https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment.
I was trying something like the below however, it overrides the other properties in the object.
let person = { age: 20 }
person = { ...getNames() }
I don't think this will work well with async/await functions either, as they return a promise.
let person = { age: 20 }
person = { ...await getNames() }
You could probably try something like this:
({firstName: person.fistName, lastName: person.lastName} = getNames());
You would need person defined as an object beforehand.
You can use Object.assign for this.. For example.
let person = { firstName: 'John', lastName: 'Doe', age: 67, //etc... }
let newPerson = Object.assign(person, getNames())
console.log(newPerson)
// Expected output: `{ firstName: 'newFirstName', lastName: 'newLastName', age: 67, etc... }`
You can view more on Object.assign here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

Remove property from a copied object while retaining property in original object [duplicate]

This question already has answers here:
How do I correctly clone a JavaScript object?
(81 answers)
Closed 3 years ago.
Why is my Employee object being changed when I've replicated it and I'm making changes to my new variable?
const Employee = { firstname: 'John', lastname: 'Doe' }
const EmployeeModifier = Employee;
console.log(EmployeeModifier.firstname);
delete EmployeeModifier.firstname;
console.log(Employee.firstname);
Right now this returns
> "John"
> undefined
Ideally it would return
> "John"
> "John"
But something is causing the delete command to remove from BOTH Employee and EmployeeModifier. Why? And how can I change this?
Because it's a reference to the original object. You will need to do a shallow/deep copy.
This is probably sufficient for you:
const oldObject = {
firstname: 'John',
address: {
street: '123 Street',
city: 'Fake Town'
}
}
const newObject = JSON.parse(JSON.stringify(oldObject));
This method has it's own problems, though. You can also use lodash's cloneDeep which is going to cover more cases.
Read here for more information on shallow/deep copying.

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" } )

Categories

Resources