Javascript delete object from object - javascript

I have following function that should delete an object in object under following id:
contactDeleteCounter++;
console.log(orderContactIds);
console.log(deletePosition);
console.log(orderContactIds[deletePosition]);
delete orderContactIds.deletePosition;
console.log(orderContactIds.deletePosition);
console.log(orderContactIds);
console.log(deletePosition);
The problem is that i everything works great in Chrome, but Firebug in Firefoxshows me following output:
Object { 0={...}, 1={...}, 2={...}}
2
Object { id= "20" , type= "1" }
undefined
Object { 0={...}, 1={...}, 2={...}}
2
As you see, the attribute is undefined, but when i look in the object, it is still there...?

The answer is to create a callback and to make async Jquery:
function deleteCallback(deletePosition) {
$.ajaxSetup({
async : false
});
console.log(orderContactIds);
console.log(deletePosition);
console.log(orderContactIds[deletePosition]);
delete orderContactIds[deletePosition];
console.log(orderContactIds.deletePosition);
console.log(orderContactIds);
console.log(deletePosition);
$.ajaxSetup({
async : true
});
}

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.

Related

WeakSet: garbage collection doesn't work? [duplicate]

The WeakSet is supposed to store elements by weak reference. That is, if an object is not referenced by anything else, it should be cleaned from the WeakSet.
I have written the following test:
var weakset = new WeakSet(),
numbers = [1, 2, 3];
weakset.add(numbers);
weakset.add({name: "Charlie"});
console.log(weakset);
numbers = undefined;
console.log(weakset);
Even though my [1, 2, 3] array is not referenced by anything, it's not being removed from the WeakSet. The console prints:
WeakSet {[1, 2, 3], Object {name: "Charlie"}}
WeakSet {[1, 2, 3], Object {name: "Charlie"}}
Why is that?
Plus, I have one more question. What is the point of adding objects to WeakSets directly, like this:
weakset.add({name: "Charlie"});
Are those Traceur's glitches or am I missing something?
And finally, what is the practical use of WeakSet if we cannot even iterate through it nor get the current size?
it's not being removed from the WeakSet. Why is that?
Most likely because the garbage collector has not yet run. However, you say you are using Traceur, so it just might be that they're not properly supported. I wonder how the console can show the contents of a WeakSet anyway.
What is the point of adding objects to WeakSets directly?
There is absolutely no point of adding object literals to WeakSets.
What is the practical use of WeakSet if we cannot even iterate through it nor get the current size?
All you can get is one bit of information: Is the object (or generically, value) contained in the set?
This can be useful in situations where you want to "tag" objects without actually mutating them (setting a property on them). Lots of algorithms contain some sort of "if x was already seen" condition (a JSON.stringify cycle detection might be a good example), and when you work with user-provided values the use of a Set/WeakSet would be advisable. The advantage of a WeakSet here is that its contents can be garbage-collected while your algorithm is still running, so it helps to reduce memory consumption (or even prevents leaks) when you are dealing with lots of data that is lazily (possibly even asynchronously) produced.
This is a really hard question. To be completely honest I had no idea in the context of JavaScript so I asked in esdiscuss and got a convincing answer from Domenic.
WeakSets are useful for security and validation reasons. If you want to be able to isolate a piece of JavaScript. They allow you to tag an object to indicate it belongs to a special set of object.
Let's say I have a class ApiRequest:
class ApiRequest {
constructor() {
// bring object to a consistent state, use platform code you have no direct access to
}
makeRequest() {
// do work
}
}
Now, I'm writing a JavaScript platform - my platform allows you to run JavaScript to make calls - to make those calls you need a ApiRequest - I only want you to make ApiRequests with the objects I give you so you can't bypass any constraints I have in place.
However, at the moment nothing is stopping you from doing:
ApiRequest.prototype.makeRequest.call(null, args); // make request as function
Object.create(ApiRequest.prototype).makeRequest(); // no initialization
function Foo(){}; Foo.prototype = ApiRequest.prototype; new Foo().makeRequest(); // no super
And so on, note that you can't keep a normal list or array of ApiRequest objects since that would prevent them from being garbage collected. Other than a closure, anything can be achieved with public methods like Object.getOwnPropertyNames or Object.getOwnSymbols. So you one up me and do:
const requests = new WeakSet();
class ApiRequest {
constructor() {
requests.add(this);
}
makeRequest() {
if(!request.has(this)) throw new Error("Invalid access");
// do work
}
}
Now, no matter what I do - I must hold a valid ApiRequest object to call the makeRequest method on it. This is impossible without a WeakMap/WeakSet.
So in short - WeakMaps are useful for writing platforms in JavaScript. Normally this sort of validation is done on the C++ side but adding these features will enable moving and making things in JavaScript.
(Of course, everything a WeakSet does a WeakMap that maps values to true can also do, but that's true for any map/set construct)
(Like Bergi's answer suggests, there is never a reason to add an object literal directly to a WeakMap or a WeakSet)
By definition, WeakSet has only three key functionalities
Weakly link an object into the set
Remove a link to an object from the set
Check if an object has already been linked to the set
Sounds more pretty familiar?
In some application, developers may need to implement a quick way to iterate through a series of data which is polluted by lots and lots of redundancy but you want to pick only ones which have not been processed before (unique). WeakSet could help you. See an example below:
var processedBag = new WeakSet();
var nextObject = getNext();
while (nextObject !== null){
// Check if already processed this similar object?
if (!processedBag.has(nextObject)){
// If not, process it and memorize
process(nextObject);
processedBag.add(nextObject);
}
nextObject = getNext();
}
One of the best data structure for application above is Bloom filter which is very good for a massive data size. However, you can apply the use of WeakSet for this purpose as well.
A "weak" set or map is useful when you need to keep an arbitrary collection of things but you don't want their presence in the collection from preventing those things from being garbage-collected if memory gets tight. (If garbage collection does occur, the "reaped" objects will silently disappear from the collection, so you can actually tell if they're gone.)
They are excellent, for example, for use as a look-aside cache: "have I already retrieved this record, recently?" Each time you retrieve something, put it into the map, knowing that the JavaScript garbage collector will be the one responsible for "trimming the list" for you, and that it will automatically do so in response to prevailing memory conditions (which you can't reasonably anticipate).
The only drawback is that these types are not "enumerable." You can't iterate over a list of entries – probably because this would likely "touch" those entries and so defeat the purpose. But, that's a small price to pay (and you could, if need be, "code around it").
WeakSet is a simplification of WeakMap for where your value is always going to be boolean true. It allows you to tag JavaScript objects so to only do something with them once or to maintain their state in respect to a certain process. In theory as it doesn't need to hold a value it should use a little less memory and perform slightly faster than WeakMap.
var [touch, untouch] = (() => {
var seen = new WeakSet();
return [
value => seen.has(value)) || (seen.add(value), !1),
value => !seen.has(value) || (seen.delete(value), !1)
];
})();
function convert(object) {
if(touch(object)) return;
extend(object, yunoprototype); // Made up.
};
function unconvert(object) {
if(untouch(object)) return;
del_props(object, Object.keys(yunoprototype)); // Never do this IRL.
};
Your console was probably incorrectly showing the contents due to the fact that the garbage collection did not take place yet. Therefore since the object wasn't garbage collected it would show the object still in weakset.
If you really want to see if a weakset still has a reference to a certain object then use the WeakSet.prototype.has() method. This method, as the name implies returns a boolean indicating wether the object still exists in the weakset.
Example:
var weakset = new WeakSet(),
numbers = [1, 2, 3];
weakset.add(numbers);
weakset.add({name: "Charlie"});
console.log(weakset.has(numbers));
numbers = undefined;
console.log(weakset.has(numbers));
Let me answer the first part, and try to avoid confusing you further.
The garbage collection of dereferenced objects is not observable! It would be a paradox, because you need an object reference to check if it exists in a map. But don't trust me on this, trust Kyle Simpson:
https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/es6%20%26%20beyond/ch5.md#weakmaps
The problem with a lot of explanations I see here, is that they re-reference a variable to another object, or assign it a primitive value, and then check if the WeakMap contains that object or value as a key. Of course it doesn't! It never had that object/value as a key!
So the final piece to this puzzle: why does inspecting the WeakMap in a console still show all those objects there, even after you've removed all of your references to those objects? Because the console itself keeps persistent references to those Objects, for the purpose of being able to list all the keys in the WeakMap, because that is something that the WeakMap itself cannot do.
While I'm searching about use cases of Weakset I found these points:
"The WeakSet is weak, meaning references to objects in a WeakSet are held weakly.
If no other references to an object stored in the WeakSet exist, those objects can be garbage collected."
##################################
They are black boxes: we only get any data out of a WeakSet if we have both the WeakSet and a value.
##################################
Use Cases:
1 - to avoid bugs
2 - it can be very useful in general to avoid any object to be visited/setup twice
Refrence: https://esdiscuss.org/topic/actual-weakset-use-cases
3 - The contents of a WeakSet can be garbage collected.
4 - Possibility of lowering memory utilization.
Refrence: https://www.geeksforgeeks.org/what-is-the-use-of-a-weakset-object-in-javascript/
##################################
Example on Weakset: https://exploringjs.com/impatient-js/ch_weaksets.html
I Advice you to learn more about weak concept in JS: https://blog.logrocket.com/weakmap-weakset-understanding-javascript-weak-references/

How delete a property of Object without "delete" operation

I need to delete the property of Object. Given an "id", I must delete value[id]. I try this code:
delete value[id];
But the delete operator deletes only a reference, never an object itself.Anyone can suggest me any methods to delete forever a objects property?
JavaScript doesn't allow you to do such a thing, it is garbage collected, this means you have no direct control over what happens in memory. You can only delete a reference. Make sure you delete it anywhere else it is used if you want it gone forever.
FROM Mozilla
go through the link, it explains it properly..
Main points from the link is added below..
Unlike what common belief suggests, the delete operator has nothing to do with directly freeing memory (it only does indirectly via breaking references. See the memory management page for more details).
If the delete operator succeeds, it removes the property from the object entirely. However, if a property with the same name exists on the object's prototype chain, the object will inherit that property from the prototype.
delete is only effective on an object's properties. It has no effect on variable or function names.
While sometimes mis-characterized as global variables, assignments that don't specify an object (e.g. x = 5) are actually property assignments on the global object.
delete can't remove certain properties of predefined objects (like Object, Array, Math etc). These are described in ECMAScript 5 and later as non-configurable.

Backbone.js model.get() returning 'undefined' even though I can see the attributes in console.log

I have a model instance, which I set another model instance on, i.e model.set('rsvp', new App.Rsvp).
When I iterate over the collection to generate the list of them in the view, I get undefined when calling model.rsvp.get('attending').
Yet when I do a console.log(model.rsvp) I get this:
Rsvp
_changing: false
_escapedAttributes: Object
_moreChanges: false
_previousAttributes: Object
_setting: false
attributes: Object
attending: true
created_at: "2012-03-28T09:42:22-05:00"
event_id: 20
id: 12
updated_at: "2012-03-28T09:42:22-05:00"
user_id: 3
__proto__: Object
cid: "c53"
id: 12
__proto__: Rsvp
So it would appear that there is no issue with the object, yet the get returns undefined.
I must admit my Javascript skill is still pretty weak. What am I missing here?
console.log( Object ) can cheat you. It won't show you the state of the Object in the moment of calling console.log.
Check this jsFiddle and open the console. You see how the console.log shows you the state of the Object at the end of the script and not in the moment of the console.log call.
For more reliable info call console.log with simpler values.
(tested is Chrome, Firefox and Safari over OSX)
Read this for more detailed information: Backbone.js Empty Array Attribute
In theory what you are doing should work, but it's probably not a good idea to bypass attributes and store properties directly on model instances. Here's a jsfiddle that shows it works in concept. My guess is that your model instance is getting recreated from source data via fetch somewhere else in your code so the model.rsvp property disappears. That or model is not the same instance you think it is.
model.rsvp = foo; (lets call this code bit #1) which is equivalently model['rsvp'] = foo; is not the same as model.set({'rsvp':foo}); (code bit #2). If you want to tack another model instance foo (or some other object or value) onto a model instance model, use the code bit #1 or its equivalent. If you want to add an attribute value pair to a model instance that might eventually be permanently stored somewhere, use the code bit #2. Likewise, you're only going to have model.rsvp defined if you used model.rsvp = foo; or model['rsvp'] = foo;

Deleting properties of objects conditionally

I have an object that may or may not have the properties I want to delete; the properties are added at runtime. This is how I'm writing the code:
if (MyObject.hasOwnProperty("SomeProperty")) {
delete MyObject['SomeProperty'];
}
If I remove the condition to test if the property doesn't exist, the code doesn't crash but I'm wondering if this is just because I'm running it in Chrome or if it's valid javascript. In other words, can I write delete MyObject['SomeProperty']; without the .hasOwnProperty statement and be fine even when the object won't have the property.
The conditional here is unnecessary. The delete operation will do nothing if the property doesn't exist on the object. It doesn't remove inherited properties, either.
Delete Documentation

How does the browser's javascript garbage collection work?

Do I have to destroy instances myself? ...if I don't assign them a variable...will they automatically go away?
new ImageUploadView();
vs
var Iu = ImageUploadView();
If there is no reference to an object in javascript, the garbage collector will clean it up.
The way the garbage collector works is it looks for javascript objects for which nobody has a reference to. If nobody has a reference to it, then it can't be used again, so it can be deleted and the memory it occupied reclaimed. On the other hand, if any javascript entity still has a reference to the object, then it is still "in use" and cannot be deleted.
In your first code example:
new ImageUploadView();
unless the constructor of the object stores away the this pointer into some other variable or object or creates some closure that causes references to the object to be held, then there will be no reference to this new object and it will be cleaned up by the garbage collector.
If you second code example:
var Iu = ImageUploadView();
as long as the Iu variable exists and stays in scope it will contain whatever the ImageUploadView() function returns. Note, the second example, is just executing a function and storing it's value. It is not necessarily creating anything. If ImageUploadView() just returns true, then that's all the Iu variable will contain.
The first method is fine. Assuming that the instance of ImageUploadView is appropriately cleaning up after itself, it will be collected by the garbage collector.
With large objects, it's not necessarily a good practice to assume that the browsers built in garbage collector will clean up once it's out of scope. You're better off to clear it ourself using "delete". For example:
delete MyImageUploadView;
Edit: it may be preferable to set the object to null if it isnt being referenced as a property.

Categories

Resources