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
Related
I have an odd situation in my Javascript code which I cannot explain. So far it has been observed only on Safari/Mac.
I have a line like this:
dict[id].sliceHovered = true;
And sometimes it throws an error:
Attempted to assign to readonly property.
Also:
dict is a bare blank object which I create myself with dict={}.
id is supplied by outside data, so it can be anything (I don't yet know which particular value causes this).
sliceHovered is obviously not a name of something that Javascript has built
in.
The objects in the dict are of my own type. They have a sliceHovered member, but it's not a Javascript defined property (as in Object.defineProperty()), just a regular property (the constructor executes this.sliceHovered=false).
"use strict" is on.
Object.freeze(), Object.seal(), Object.preventExtensions() and const are not used anywhere in the entire codebase.
Thus it's extremely puzzling as to how such an error could be thrown here. If I had an indexing error and dict[id] would be undefined or null, the error would be different. My only idea is that since the dict is created as dict={} then it inherits from Object and maybe id maps to some inherited property. But that means that the object returned from dict[id] would have to be read-only itself, because sliceHovered is definitely not a name of an existing Javascript property.
However I cannot think of any Javascript objects that would be intrinsically read-only like that.
Any ideas what could be wrong here?
You can check this situation
My only idea is that since the dict is created as dict={} then it inherits from Object
with: var dict = Object.create(null);
Also try to use Object.getOwnPropertyDescriptor(dict, id) to make sure descriptors have right values.
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.
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.
In Chrome, try the following in the console. First
console = 0;
to assign the value 0 to console. Then
console // (prints `0`)
to check we have correctly overwritten console. Finally,
delete console
Surprisingly, console now holds the original Console object. In effect, the delete keyword "resurected" console, instead of exterminating it!
Is this expected behaviour? Where is this implemented in the Chromium code?
As mentioned in MDN's documentation on delete:
If the delete operator succeeds, it removes the property from the
object entirely, although this might reveal a similarly named property
on a prototype of the object.
Your delete simply unshadows native property inherited through prototype chain.
Some browsers have window inherit from native prototype and you'll have check out sources to see how property is inherited, if you really want to know that much details, but mostly they work just like JS' own.
Got it:
I've managed to prove the console is a property of the global object: just open your console and type: this.parent or window.parent. This will show a more complete list of properties and methods at your disposal. Including console: Console, about 2/3 of the way down, just below chrome: Object (interesting...:)). I thought of this when I remembered that I somehow managed to change the CSS rules of the console itself (in chrome, don't ask me how I got there, I can't remember). Bottom line: console ís a property of the window object. I think this backs up my explanation rather well.
#Randomblue: Since you're interested in how this is implemented in v8 you can check the trunk here, or browse the bleeding. Somewhere you'll find a test dir, that has a number of files that deal with delete. Special attention is given to delete used on global variables/properties: they can't be deleted, in other words: the console is never really gone. I would like to know why this answer went from being voted helpful and accepted to not-helpful and not-accepted, though...
It's perfectly simple. Console isn't some random, stand-alone, object. It's actually a property of the global object. Open your console and type this.console === console or window.console === console. It logs true, of course.
So thanks to implied globals console = 0 is pretty much the same as window.console = 0. You're sort of reassigning a property of an instance. The difference with normal objects is that the global object isn't just any old object: it's properties cannot be deleted (somewhere here on MDN). So your global is masking the console object, which is still there, you've just lost your reference too it:
var bar = window.console;
console = 12;
bar.log(console);//logs 12, bar is now an alternative reference to the console object
delete console;//unmasks the console reference
console === bar;//true
Don't, for a moment, be fooled into thinking the global object doesn't have a prototype. Just type this.constructor.name and lo and behold: Window with a capital W does appear. Another way of double checking is: Object.getPrototypeOf(this); or Object.getPrototypeOf(window);. In other words, there are prototypes to consider. Like always, the chain ends with Object.prototype:
Object.getPrototypeOf(Object.getPrototypeOf(window));
In short, there is nothing weird going on here, but the weird nature of the global object itself. It behaves as if there is some form of prototypal inheritance going on. Look at the global object as though it were set up like this:
this.prototype.window = this;//<-- window is a circular reference, global obj has no name
this.prototype.console = new Console();//this is the global object
this.hasOwnProperty(console);//false
console = 0;//implied global
When attempting to access console, JS finds the property console you've just set prior to the instance of the Console object, and happily returns its value. The same happens when we delete it, the first occurance of console is deleted, but the property higher up the prototype chain remains unchanged. The next time console is requested, JS will scan the inheritance chain and return the console instance of old. The console-object was never really gone, it was merely hidden behind a property you set yourself.
Off topic, but for completeness' sake:
There are a few more things too it than this (scope scanning prior to object/prototype chain searching), due to the special character of the global object, but this is, AFAIK, the essence of it.What you need to know is that there is no such thing (in JS) as an object without (at least) 1 prototype. That includes the global object. What you're doing merely augments the current global object's instance, delete a property and the prototype takes over again. Simple as that. That's what #Peeter hinted at with his answer: implied globals are not allowed in strict mode, because they modify the global object. Which, as I tried to explain here, is exactly what happens here.
Some properties of the window object aren't deletable. True is returned because you aren't running in strict mode. Try the following (not in console):
"use strict";
delete console;
and you will get an exception (JSFiddle).
You can read more about how this is handled at http://es5.github.com/#x11.4.1
First, this is not just the console, you can do this with every native property every browser-defined property on window.
setTimeout = 0;
setTimeout //=> 0
delete window.setTimeout;
setTimeout //=> function setTimeout() { [native code] }
Properties that are part of the ECMA-Script Spec can be fully overwritten & deleted:
Array = 0;
Array //=> 0
delete window.Array;
Array //=> ReferenceError
You can nearly overwrite any property on window, delete the overwrite and get back to the normal function.
The simple reason for this is that console and all the other native global functions browser defined properties are not linked to the DOMWindow Object via javascript but via C++. You can see the console being attached to the DOMWindow right here and the implementation of DOMWindow here
That also means that the window object is somehow a C++ Object masked as a javascript object the window object is at least partly defined by C++, and it is not prototypical inheritance doing the magic: Take for example:
window.hasOwnProperty('console') //=> true, console is defined directly on the window
window.__proto__.hasOwnProperty('console') // => false, the window prototype does not have a console property
Also, if it was prototypical inheritance, the following would lead to console returning 3:
window.__proto__.console = 3;
delete console;
console //=> still returns console;
window.hasOwnProperty('console') //=> the window still has it.
The same with a property respecting prototypical inheritance:
window.someProp = 4;
window.__proto__.someProp = 6;
someProp //=> 4
delete someProp;
someProp //=> 6
Therefore, when you set console to anything, it is gone and can only be resurrected by (hoorray for the irony): delete console.
So, what it means is that you cannot delete any native properties on the window object. Try to delete window.console when it is not overwritten, it will just pop up again. The fact that you are able to overwrite it in the first place (even in strict mode) without receiving any kind of warning (in my eyes) one of the key vulnerabilities of javascript (set setTimeout on nearly any page to 0 and see it tear itself apart), but as they say in spiderman:
With great power comes great responsibility
Update
To include a hint that this is specific to the implementation of the browser / engine and not any requirement of the language itself: In nodejs, deleting both engine-specified properties and ecma-script properties on the global object works:
delete this.console //=> true
console //=> ReferenceError
delete parseInt //=> true
parseInt //=> ReferenceError
The exact same thing happens in Firefox.
I'm assuming the following, based on observations of my own.
Variables are first checked to see if they match local variables, if not, then it will be checked to see if they match window.variable.
When you set console to 1, you set the local variable console to 1, so any lookups will see that instead of window.console (which still exists). When you delete console the local variable console gets deleted. Now any lookups of console will match window.console. That's why you get the behaviour you get.
I am assuming this based on experimenting with the JavaScript interpreter in Firefox.
And, I'm sorry about incorrect terminology (feel free to edit), I'm not that experienced with namespaces.
The delete operator removes a property from an object.
...
You can use the delete operator to delete variables declared
implicitly but not those declared with the var or the function
statement.
See delete on MDN
Edit:
See also Understanding delete if you're really into hardcore JavaScript.
What happens is you are overwriting the objects prototype, then you delete the overwritten value and what is left... is the original object, which is it's prototype.
Expected behavior. Little known fact that the Javascript console does not run in the browser's global space, but rather it runs within its own anonymous function.
I know that different browsers handle things differently, but in short -- delete does not operate as expected because it isn't operating in the global space.
If you really want to see things break, try playing with delete window.console
Ok, it is official -- I'm an idiot. One of the new features in ECMAScript is the ability to declare a property as dontdelete. Sorry about that confusion.
A clientside javascript library I've developed uses objects as hashes in some areas. It loops through objects parsed from Json data with a for...in loop using the property name as a key. eg... (pseudo code)
var conversations = {'sha1-string':{name:'foo',messages:[]}}
for(var id in conversations){
console.log(id);
console.log(conversations[id].name);
}
Unfortunately MooTools (and Prototype, etc) add methods to the global namespaces, so my for...in loops now iterate through MooTools' additions (eg. limit, round, times, each), causing errors when it applies logic to them as if it were the data expected.
As it's a library, I have to expect that it will be used with MooTools, Prototype, etc. Is there an easy way around this problem? My current solution is just to pass the object to a method which strips out the MooTools specific entries and returns the clean object, but this means also checking what Prototype and all similar libraries out there add, and seems to be a backwards way of doing things.
My other solution is to stop relying on the property name as a key, and perform validation in the loops to ensure I'm looking at the data I want to. Before I do that rewriting though, I'm wondering if anyone has a better/existing solution?
Thanks :)
If your clientside objects are not inherited from other custom objects, you see if you could use the javascript's Object.hasOwnProperty method to find out if a certain property exists in the object itself and not up in the inheritance chain via the prototype object.
For browsers that don't support this method, you can write a wrapper around to check:
var hasOwnProperty = function(object, property) {
if(object.hasOwnProperty) {
return object.hasOwnProperty(property);
}
var prop = object[property];
return typeof(prop) !== "undefined" && prop !==
object.constructor.prototype[property];
}
How to use it:
for(var key in someObj) {
if(hasOwnProperty(someObj, key)) {
// we are good to go!
}
}
If I got it correctly, you are looking for the hasOwnProperty() method.
As "limit", "round", "times" and "each" are all additional methodes of the Array prototyp you're main failure is to use "for in" to iterate over arrays. You should check the type of the object before and use "for in" only for objects and "for" for arrays.
Btw. "for in" is the slowest method to iterate over arrays.
Using both MooTools and Prototype isn't a very good idea as they modify the base prototypes and can't co-exist peacefully. That said, none of them modify Object.prototype (not anymore) so you should not see any other properties besides your own.
Did you add a plugin which is perhaps adding these properties there? Could you give a more complete example that shows where these properties are getting listed and also the versions of these libraries that you are using?
hasOwnProperty checks will solve the prototype problem, but this shouldn't be needed in the first place, so maybe it's better to find out exactly which script is messing up.
MooTools has created a Hash type just because they didn't want to modify Object.prototype. Here's a quote from the docs:
Hash
A custom Object ({}) implementation which does not account for prototypes when setting, getting, or iterating. Useful because in JavaScript, we cannot use Object.prototype. Instead, we can use Hash.prototype!