This is related to storing manipulated objects in react, but is also a general javascript question.
In react, you usually take a current state object, and add to it like so:
setFormErrors({...formErrors, agreeToRefund: 'Some message'})
where formErrors and setFormErrors is what comes out of useState() hook.
To do a delete, you have to the more verbose:
const newFormErrors = {...formErrors};
delete newFormErrors.agreeToRefund;
setFormErrors(newFormErrors)
Which is a little tedious. Is there a more abbreviated 1 liner to do this?
In 2 statements, yes, but not 1.
const {agreeToRefund , ...newFormErrors} = formErrors;
setFormErrors(newFormErrors)
But if it were me, I'd change the user of formErrors to understand a property value of null or '' instead of removing it from state entirely.
setFormErrors({...formErrors, agreeToRefund: null})
Or you can play with map and comma operator if you do not mind:
box it in a array so you can map over it to delete what you want then pop it back.
setFormErrors([{...newFormErrors}].map(obj=> (delete obj.agreeToRefund,obj)).pop())
let formErrors={fistnam:'error',lastname:'error again'}
console.log('formErrors:',formErrors)
let newFormErrors={...formErrors, agreeToRefund: 'Some message'}
console.log('newFormErrors:',newFormErrors)
let noagreeToRefund=[{...newFormErrors}].map(obj=> (delete obj.agreeToRefund,obj)).pop()//?
console.log('noagreeToRefund:',noagreeToRefund)
One option is to create a utility function (probably exported in a util library)
function newObjWithoutProperty(obj, prop) {
const newObj = { ...obj };
delete newObj[prop];
return newObj;
}
then it becomes:
setFormErrors(newObjWithoutProperty(formErrors, 'agreeToRefund'));
Related
I'm a bit confused with JavaScript's delete operator. Take the following piece of code:
var obj = {
helloText: "Hello World!"
};
var foo = obj;
delete obj;
After this piece of code has been executed, obj is null, but foo still refers to an object exactly like obj. I'm guessing this object is the same object that foo pointed to.
This confuses me, because I expected that writing delete obj deleted the object that obj was pointing to in memory—not just the variable obj.
Is this because JavaScript's Garbage Collector is working on a retain/release basis, so that if I didn't have any other variables pointing to the object, it would be removed from memory?
(By the way, my testing was done in Safari 4.)
The delete operator deletes only a reference, never an object itself. If it did delete the object itself, other remaining references would be dangling, like a C++ delete. (And accessing one of them would cause a crash. To make them all turn null would mean having extra work when deleting or extra memory for each object.)
Since Javascript is garbage collected, you don't need to delete objects themselves - they will be removed when there is no way to refer to them anymore.
It can be useful to delete references to an object if you are finished with them, because this gives the garbage collector more information about what is able to be reclaimed. If references remain to a large object, this can cause it to be unreclaimed - even if the rest of your program doesn't actually use that object.
The delete command has no effect on regular variables, only properties. After the delete command the property doesn't have the value null, it doesn't exist at all.
If the property is an object reference, the delete command deletes the property but not the object. The garbage collector will take care of the object if it has no other references to it.
Example:
var x = new Object();
x.y = 42;
alert(x.y); // shows '42'
delete x; // no effect
alert(x.y); // still shows '42'
delete x.y; // deletes the property
alert(x.y); // shows 'undefined'
(Tested in Firefox.)
"variables declared implicitly" are properties of the global object, so delete works on them like it works on any property. Variables declared with var are indestructible.
Coming from the Mozilla Documentation, "You can use the delete operator to delete variables declared implicitly but not those declared with the var statement. "
Here is the link: https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference:Operators:Special_Operators:delete_Operator
delete is not used for deleting an object in java Script.
delete used for removing an object key in your case
var obj = { helloText: "Hello World!" };
var foo = obj;
delete obj;
object is not deleted check obj still take same values delete usage:
delete obj.helloText
and then check obj, foo, both are empty object.
Setting a variable to null makes sure to break any references to objects in all browsers including circular references being made between the DOM elements and Javascript scopes. By using delete command we are marking objects to be cleared on the next run of the Garbage collection, but if there are multiple variables referencing the same object, deleting a single variable WILL NOT free the object, it will just remove the linkage between that variable and the object. And on the next run of the Garbage collection, only the variable will be cleaned.
Just found a jsperf you may consider interesting in light of this matter. (it could be handy to keep it around to complete the picture)
It compares delete, setting null and setting undefined.
But keep in mind that it tests the case when you delete/set property many times.
Aside from the GC questions, for performance one should consider the optimizations that the browser may be doing in the background ->
http://coding.smashingmagazine.com/2012/11/05/writing-fast-memory-efficient-javascript/
It appears it may be better to null the reference than to delete it as that may change the behind-the-scenes 'class' Chrome uses.
IE 5 through 8 has a bug where using delete on properties of a host object (Window, Global, DOM etc) throws TypeError "object does not support this action".
var el=document.getElementById("anElementId");
el.foo = {bar:"baz"};
try{
delete el.foo;
}catch(){
//alert("Curses, drats and double double damn!");
el.foo=undefined; // a work around
}
Later if you need to check where the property has a meaning full value use el.foo !== undefined because "foo" in el
will always return true in IE.
If you really need the property to really disappear...
function hostProxy(host){
if(host===null || host===undefined) return host;
if(!"_hostProxy" in host){
host._hostproxy={_host:host,prototype:host};
}
return host._hostproxy;
}
var el=hostProxy(document.getElementById("anElementId"));
el.foo = {bar:"baz"};
delete el.foo; // removing property if a non-host object
if your need to use the host object with host api...
el.parent.removeChild(el._host);
I stumbled across this article in my search for this same answer. What I ended up doing is just popping out obj.pop() all the stored values/objects in my object so I could reuse the object. Not sure if this is bad practice or not. This technique came in handy for me testing my code in Chrome Dev tools or FireFox Web Console.
This work for me, although its not a good practice. It simply delete all the
the associated element with which the object belong.
for (element in homeService) {
delete homeService[element];
}
The delete operator deletes an object, an object's property, or an element from an array. The operator can also delete variables which are not declared with the var statement.
In the example below, 'fruits' is an array declared as a var and is deleted (really??)
delete objectName
delete objectName.property
delete objectName[index]
delete property // The command acts only within a with statement.
var fruits = new Array("Orange", "Apple", "Banana", "Chery");
var newParagraph = document.createElement("p");
var newText = document.createTextNode("Fruits List : " + fruits);
newParagraph.appendChild(newText);
document.body.appendChild(newParagraph);
//Delete the array object.
delete fruits;
var newParagraph1 = document.createElement("p");
var newText1 = document.createTextNode("Display the Fruits after delete the array object - Fruits List : "+ fruits;);
newParagraph1.appendChild(newText1);
document.body.appendChild(newParagraph1);
https://www.w3resource.com/javascript/operators/delete.php
We have multiple ways to Delete the Object property.
Arrow Function: We can also use the arrow function to remove the property from an object which is a one-liner solution.
const obj = {
'first': 'one',
'second': 'two',
'third': 'three'
}
const fn = (key, { [key]: deletedKey, ...others }) => others;
console.log(fn('first', obj)) // { 'second': 'two', 'third': 'three' }
Reduce Method: We can use the reduce method to delete the specific property from the original object in javascript.
const obj = {
'first': 'one',
'second': 'two',
'third': 'three'
}
const exceptSecond = Object.keys(obj).reduce((acc, key) => {
if (key !== 'second') {
acc[key] = obj[key]
}
return acc
}, {})
console.log(exceptSecond) // { 'first': 'one', 'third': 'three' }
Delete: This is easy simple way to delete.
delete obj.first;
// Or
delete obj['first'];
Using unset, Omit, Pic Method from "loadash" lib:
import { unset } from 'lodash'
const obj = {
'first': 'one',
'second': 'two',
'third': 'three'
}
unset(obj, 'third') // true
console.log(obj) // { 'first': 'one', 'second': 'two' }
// Using omit
import { omit } from 'lodash'
const obj1 = {
'first': 'one',
'second': 'two',
'third': 'three'
}
omit(obj1, [ 'first', 'second' ])
console.log(obj1)
Reflect Delete Property: This is the new built-in Object introduced in ES6. Now it is possible to delete object property by calling the deleted property() function from this Refect Object.
This function is equivalent to what we have discussed with the delete operator in the first method.
const someObject = {
'first': 'one',
'second': 'two',
'third': 'three'
}
Reflect.deleteProperty(someObject, 'second')
console.log(someObject) // { 'first': 'one', 'third': 'three' }
If you want the object to be deleted based on its value do this:
Object.keys(obj).forEach((key) => {
if (obj[key] === "Hello World!") {
delete obj[key];
}
});
But deleting an object is not a good idea. So, set it to undefined, so that when you pass it to a parameter. It won't be showing. No need to delete.
Object.keys(obj).forEach((key) => {
if (obj[key] === "Hello World!") {
obj[key] = undefined;
}
});
I have a JavaScript object with some static attribute values, dynamic attribute values and methods. Each time I need one of these objects, I will need 10 of them. Each of the 10 objects gets initialized by a dedicated object literal. That happens under 3 different contexts of a user doing something on a data entry form. User actions can cause the contexts to happen in any order, any number of times, but the same 10 objects will always be created in each context. By "same" I mean the static values for a "no_matl" object will be identical each time a "no_matl" object is created ... only a few dynamic attribute values (field value, previous value, date/time, context ID) are different for each context.
Is there a smarter way to do the initialization currently done with the const object literal? Originally I passed a bunch of params to the constructor and initialized the static attributes from those. The object literal approach seemed cleaner. Maybe there's a better way?
// object literals used to initialize a each of the 10
// different type objects.
const FIELD_NOMATERIAL = {
DispName: 'No Material',
DbName: 'NO_MATERIAL',
TrueVal: 'Yes',
InitVal: '',
DispWhenSet: 'yes',
DispWhenNotSet: ''
};
const FIELD_CPCAT = { ... same attributes, different values ...};
const FIELD_HCN = { ... same attributes, different values ...};
// ... 7 more like this ...
// context 1
var no_matl = new MyField(FIELD_NOMATERIAL),
cpcap = new MyField(FIELD_CPCAT),
hcn = new MyField(FIELD_HCN) .... 7 more like this
// object definition
function MyField() {
if (arguments.length == 1 && typeof(arguments[0]) === 'object' ) {
this.DispName = arguments[0].DispName ;
this.DbName = arguments[0].DbName ;
// .... etc for rest of static attributes ...
}
}
Sounds like what you want is a copy of the original object that can change values without changing the original. Try this:
const FIELD_NOMATERIAL = {
DispName: 'No Material',
DbName: 'NO_MATERIAL',
TrueVal: 'Yes',
InitVal: '',
DispWhenSet: 'yes',
DispWhenNotSet: ''
};
function getFreshCopy(original) {
return Object.assign({}, original);
}
var no_matl = getFreshCopy(FIELD_NOMATERIAL);
Using Object.assign({}, obj) will create a new copy that can be changed without the original values changing. no_matl can be adjusted and FIELD_NOMATERIAL remains in its original state.
Note that const means the variable cannot be assigned a new value. It does not mean that the contents of the object cannot be changed. That means the following is true:
const noChange = { a: 7 };
noChange.a = 8; // this is fine because 'a' is allowed to change
noChange = "hello"; // this gives TypeError: Assignment to constant variable.
While building a Todo app, I want to filter out an object out of my array with a remove function. So far I got this.
deleteTask(task) {
let taskList = this.state.tasks;
var newTask = taskList.filter(function(_task) { return _task != task})
this.setState({
tasks: newTask
});
}
Only problem is, the function returns the whole array while using the function.
So the Task argument that should return just an object out of my array returns the whole array instead while in my newTask var.
How can I bind or make this function work?
The array which I am wanting to remove an object from is not located in the same Component, dont know if that matters. But for extra info.
First off, let's see why _task != task doesn't work as you need. Try this:
const a = { x: 10, y: 'hello' };
const b = { x: 10, y: 'hello' };
console.log(
a==b,
a===b,
Object.is(a,b)
);
Suprising, eh? Read this for more details.
Anyway, you should refactor your code to include an id property in your tasks, so that you can compare two tasks with their ids - no need to worry about weird implementations of object comparisons in JavaScript!
This should then work:
deleteTask(taskId) {
this.setState(prevState => ({
tasks: prevState.tasks.filter(task => task.id !== taskId)
}));
}
Equality operator in javascript compares the references of the object. So even if both object have same value, since they point to different instances, == will always return false. So as I see you have two options:
Refactor your code to include a id part and which that to compare two tasks.
Use some library like lodash or underscore for deep comparison
I have a very simple question, but…
The code (in a redux/react-native app) of a reducer:
...
case SAMPLES_DELETE_REQUEST_SUCCESS: {
var newState = Object.assign({}, state);
const indexToDelete = newState.samples.findIndex( sample => {
return sample.id == action.sample.id
})
newState.samples.splice(indexToDelete, 1)
debugger;
return newState
}
...
Ok, I copy the state and store it into newState. But when I do newState.samples.splice(indexToDelete, 1), newState is correctly modified, but also state! Why?? I must be tired…
splice function modifies original array. Object.assign does not do deep cloning. Therefore you are still modifying the original state!
You will have to manually copy the nested object(or array) you want to clone:
// Deep Clone
obj1 = { a: 0 , b: { c: 0}};
let obj2 = JSON.parse(JSON.stringify(obj1));
As someone mention before you could use JSON.parse(JSON.stringify(obj)) to create a new copy of the entire object (nested object as well). If you don't want to do that, you could check libraries like Inmutable JS
Also if you want to use spread notation, a better way to do that will be:
return {
...state,
samples: state.samples.filter(sample => sample.id !== action.sample.id)
}
I'm a bit confused with JavaScript's delete operator. Take the following piece of code:
var obj = {
helloText: "Hello World!"
};
var foo = obj;
delete obj;
After this piece of code has been executed, obj is null, but foo still refers to an object exactly like obj. I'm guessing this object is the same object that foo pointed to.
This confuses me, because I expected that writing delete obj deleted the object that obj was pointing to in memory—not just the variable obj.
Is this because JavaScript's Garbage Collector is working on a retain/release basis, so that if I didn't have any other variables pointing to the object, it would be removed from memory?
(By the way, my testing was done in Safari 4.)
The delete operator deletes only a reference, never an object itself. If it did delete the object itself, other remaining references would be dangling, like a C++ delete. (And accessing one of them would cause a crash. To make them all turn null would mean having extra work when deleting or extra memory for each object.)
Since Javascript is garbage collected, you don't need to delete objects themselves - they will be removed when there is no way to refer to them anymore.
It can be useful to delete references to an object if you are finished with them, because this gives the garbage collector more information about what is able to be reclaimed. If references remain to a large object, this can cause it to be unreclaimed - even if the rest of your program doesn't actually use that object.
The delete command has no effect on regular variables, only properties. After the delete command the property doesn't have the value null, it doesn't exist at all.
If the property is an object reference, the delete command deletes the property but not the object. The garbage collector will take care of the object if it has no other references to it.
Example:
var x = new Object();
x.y = 42;
alert(x.y); // shows '42'
delete x; // no effect
alert(x.y); // still shows '42'
delete x.y; // deletes the property
alert(x.y); // shows 'undefined'
(Tested in Firefox.)
"variables declared implicitly" are properties of the global object, so delete works on them like it works on any property. Variables declared with var are indestructible.
Coming from the Mozilla Documentation, "You can use the delete operator to delete variables declared implicitly but not those declared with the var statement. "
Here is the link: https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference:Operators:Special_Operators:delete_Operator
delete is not used for deleting an object in java Script.
delete used for removing an object key in your case
var obj = { helloText: "Hello World!" };
var foo = obj;
delete obj;
object is not deleted check obj still take same values delete usage:
delete obj.helloText
and then check obj, foo, both are empty object.
Setting a variable to null makes sure to break any references to objects in all browsers including circular references being made between the DOM elements and Javascript scopes. By using delete command we are marking objects to be cleared on the next run of the Garbage collection, but if there are multiple variables referencing the same object, deleting a single variable WILL NOT free the object, it will just remove the linkage between that variable and the object. And on the next run of the Garbage collection, only the variable will be cleaned.
Just found a jsperf you may consider interesting in light of this matter. (it could be handy to keep it around to complete the picture)
It compares delete, setting null and setting undefined.
But keep in mind that it tests the case when you delete/set property many times.
Aside from the GC questions, for performance one should consider the optimizations that the browser may be doing in the background ->
http://coding.smashingmagazine.com/2012/11/05/writing-fast-memory-efficient-javascript/
It appears it may be better to null the reference than to delete it as that may change the behind-the-scenes 'class' Chrome uses.
IE 5 through 8 has a bug where using delete on properties of a host object (Window, Global, DOM etc) throws TypeError "object does not support this action".
var el=document.getElementById("anElementId");
el.foo = {bar:"baz"};
try{
delete el.foo;
}catch(){
//alert("Curses, drats and double double damn!");
el.foo=undefined; // a work around
}
Later if you need to check where the property has a meaning full value use el.foo !== undefined because "foo" in el
will always return true in IE.
If you really need the property to really disappear...
function hostProxy(host){
if(host===null || host===undefined) return host;
if(!"_hostProxy" in host){
host._hostproxy={_host:host,prototype:host};
}
return host._hostproxy;
}
var el=hostProxy(document.getElementById("anElementId"));
el.foo = {bar:"baz"};
delete el.foo; // removing property if a non-host object
if your need to use the host object with host api...
el.parent.removeChild(el._host);
I stumbled across this article in my search for this same answer. What I ended up doing is just popping out obj.pop() all the stored values/objects in my object so I could reuse the object. Not sure if this is bad practice or not. This technique came in handy for me testing my code in Chrome Dev tools or FireFox Web Console.
This work for me, although its not a good practice. It simply delete all the
the associated element with which the object belong.
for (element in homeService) {
delete homeService[element];
}
The delete operator deletes an object, an object's property, or an element from an array. The operator can also delete variables which are not declared with the var statement.
In the example below, 'fruits' is an array declared as a var and is deleted (really??)
delete objectName
delete objectName.property
delete objectName[index]
delete property // The command acts only within a with statement.
var fruits = new Array("Orange", "Apple", "Banana", "Chery");
var newParagraph = document.createElement("p");
var newText = document.createTextNode("Fruits List : " + fruits);
newParagraph.appendChild(newText);
document.body.appendChild(newParagraph);
//Delete the array object.
delete fruits;
var newParagraph1 = document.createElement("p");
var newText1 = document.createTextNode("Display the Fruits after delete the array object - Fruits List : "+ fruits;);
newParagraph1.appendChild(newText1);
document.body.appendChild(newParagraph1);
https://www.w3resource.com/javascript/operators/delete.php
We have multiple ways to Delete the Object property.
Arrow Function: We can also use the arrow function to remove the property from an object which is a one-liner solution.
const obj = {
'first': 'one',
'second': 'two',
'third': 'three'
}
const fn = (key, { [key]: deletedKey, ...others }) => others;
console.log(fn('first', obj)) // { 'second': 'two', 'third': 'three' }
Reduce Method: We can use the reduce method to delete the specific property from the original object in javascript.
const obj = {
'first': 'one',
'second': 'two',
'third': 'three'
}
const exceptSecond = Object.keys(obj).reduce((acc, key) => {
if (key !== 'second') {
acc[key] = obj[key]
}
return acc
}, {})
console.log(exceptSecond) // { 'first': 'one', 'third': 'three' }
Delete: This is easy simple way to delete.
delete obj.first;
// Or
delete obj['first'];
Using unset, Omit, Pic Method from "loadash" lib:
import { unset } from 'lodash'
const obj = {
'first': 'one',
'second': 'two',
'third': 'three'
}
unset(obj, 'third') // true
console.log(obj) // { 'first': 'one', 'second': 'two' }
// Using omit
import { omit } from 'lodash'
const obj1 = {
'first': 'one',
'second': 'two',
'third': 'three'
}
omit(obj1, [ 'first', 'second' ])
console.log(obj1)
Reflect Delete Property: This is the new built-in Object introduced in ES6. Now it is possible to delete object property by calling the deleted property() function from this Refect Object.
This function is equivalent to what we have discussed with the delete operator in the first method.
const someObject = {
'first': 'one',
'second': 'two',
'third': 'three'
}
Reflect.deleteProperty(someObject, 'second')
console.log(someObject) // { 'first': 'one', 'third': 'three' }
If you want the object to be deleted based on its value do this:
Object.keys(obj).forEach((key) => {
if (obj[key] === "Hello World!") {
delete obj[key];
}
});
But deleting an object is not a good idea. So, set it to undefined, so that when you pass it to a parameter. It won't be showing. No need to delete.
Object.keys(obj).forEach((key) => {
if (obj[key] === "Hello World!") {
obj[key] = undefined;
}
});