Lets say I want to check whether a property exists within an Object or not. I was looking at two methods:
if(object.hasOwnProperty(key)) { /* do this */ }
OR
if(object[key]) { /* do this */ }
Assuming that we'll never have object = { key: false };
What are the tradeoffs of using one over the other ?
object[key] checks the entire object chain, including the prototype chain.
object.hasOwnProperty(key) checks to see if the key property is assigned directly to the object and does not look in the prototype chain.
So, which one to use depends upon which result you want.
See a simple demonstration using the hasOwnProperty property: http://jsfiddle.net/jfriend00/6zhv87rk/ which is on the prototype for an object.
You would typically use object.hasOwnProperty(key) when your key can be any arbitrary string and you want to make absolutely sure that it will never conflict with a built-in property on the Object prototype. In fact, if you really want to protect yourself, you even use this Object.prototype.hasOwnProperty.call(object, key) so even the hasOwnProperty property could be used with your object. Cases like this would be when you're using a Javascript object as a hash lookup or dictionary-type object with arbitrary key values.
You would typically use object[key] when you are not concerned about such a conflict because you know what types of keys will be on your object and you know they won't conflict because this version is just shorter and a bit easier to read.
Related
I read that we should always use hasOwnProperty when looping an object, because the object can be modified by something else to include some keys we don't want.
But is this always required? Are there situations where it's not needed? Is this required for local variables too?
function my(){
var obj = { ... };
for(var key in obj){
if(obj.hasOwnProperty(key)){
safe
}
}
}
I just don't like adding an extra if inside the loop if I don't have to.
Death to hasOwnProperty
This guy says I shouldn't use it at all any more.
Object.hasOwnProperty determines if the whole property is defined in the object itself or in the prototype chain.
In other words: do the so-called check if you want properties (either with data or functions) coming from no other place than the object itself.
For example:
function A() {
this.x = "I'm an own property";
}
A.prototype.y = "I'm not an own property";
var instance = new A();
var xIsOwnProperty = instance.hasOwnProperty("x"); // true
var yIsOwnProperty = instance.hasOwnProperty("y"); // false
Do you want to avoid the whole check if you want own properties only?
Since ECMAScript 5.x, Object has a new function Object.keys which returns an array of strings where its items are the own properties from a given object:
var instance = new A();
// This won't contain "y" since it's in the prototype, so
// it's not an "own object property"
var ownPropertyNames = Object.keys(instance);
Also, since ECMAScript 5.x, Array.prototype has Array.prototype.forEach which let’s perform a for-each loop fluently:
Object.keys(instance).forEach(function(ownPropertyName) {
// This function will be called for each found "own property", and
// you don't need to do the instance.hasOwnProperty check any more
});
When you're using for (var key in obj) it will loop through the given object + its parent objects' properties on the prototype chain until it reaches the end of the chain. As you want to check only a specific object's properties, you need to use hasOwnProperty.
This is not needed in for (var i = 0; i < length; i++) or data.forEach().
YES, use it always with for ... in
There are some nice answers here describing what hasOwnProperty() does and offering other solutions.
But none do provide an answer to what this question and #João in comments asks.
Is this always required?
In other words,
if the object is mine, if I have control over it, if the object is defined as my own local variable,
do I still need to use hasOwnProperty()?
The complication with this question is, that the control over the variable of Object type is not what's important in this consideration.
What's important is the control over the Object type itself.
If the question is slightly rephrased to: "Is the use of hasOwnProperty() required if I have full control over the JS script, where it's used and everything in its or parent scopes?"
Then no, you don't need to use the hasOwnProperty().
But the full control over the environment is not something you should count on.
Consider this example
var variableCreatedByInocentUser = { amisane: 'yes' };
for (let key in variableCreatedByInocentUser) {
console.log(key +'? '+ variableCreatedByInocentUser[key]);
}
console.log('-----');
Object.prototype.amicrazy = 'yes, you redefined Object type';
for (let key in variableCreatedByInocentUser) {
console.log(key +'? '+ variableCreatedByInocentUser[key]);
}
console.log('-----');
for (let key in variableCreatedByInocentUser) {
if (!variableCreatedByInocentUser.hasOwnProperty(key)) { continue; }
console.log(key +'? '+ variableCreatedByInocentUser[key]);
}
It's fine to drop the hasOwnProperty() only until someone somewhere redefines the Object type.
Before or even after your script is started.
The effect is retroactive. Even if you declared your variable "using original Object type",
it does not work as expected in JS and the redefined Object type will also affect such variables created before.
Even though the redefining of base types is discouraged, it's being done in some frameworks.
Such framework could be included and introduced into your global scope and break your script.
There might also be a safety issue. The Object could be redefined with malicious intention, making your loops perform additional tasks.
If you want to follow good practices, you should always consider all possible scenarios, like that the code you're writing could be reused or inserted, or joined with another project.
Use hasOwnProperty() even when it might seem not necessary and wasteful.
hasOwnProperty expects the property name as a string.
When you call Test.hasOwnProperty(name) you are passing it the value of the name variable (which doesn't exist), just as it would if you wrote alert(name).
Every object descended from Object inherits the hasOwnProperty method. This method can be used to determine whether an object has the specified property as a direct property of that object;
I read that we should always use hasOwnProperty when looping an object, because the object can be modified by something else to include some keys we don't want.
But is this always required? Are there situations where it's not needed? Is this required for local variables too?
function my(){
var obj = { ... };
for(var key in obj){
if(obj.hasOwnProperty(key)){
safe
}
}
}
I just don't like adding an extra if inside the loop if I don't have to.
Death to hasOwnProperty
This guy says I shouldn't use it at all any more.
Object.hasOwnProperty determines if the whole property is defined in the object itself or in the prototype chain.
In other words: do the so-called check if you want properties (either with data or functions) coming from no other place than the object itself.
For example:
function A() {
this.x = "I'm an own property";
}
A.prototype.y = "I'm not an own property";
var instance = new A();
var xIsOwnProperty = instance.hasOwnProperty("x"); // true
var yIsOwnProperty = instance.hasOwnProperty("y"); // false
Do you want to avoid the whole check if you want own properties only?
Since ECMAScript 5.x, Object has a new function Object.keys which returns an array of strings where its items are the own properties from a given object:
var instance = new A();
// This won't contain "y" since it's in the prototype, so
// it's not an "own object property"
var ownPropertyNames = Object.keys(instance);
Also, since ECMAScript 5.x, Array.prototype has Array.prototype.forEach which let’s perform a for-each loop fluently:
Object.keys(instance).forEach(function(ownPropertyName) {
// This function will be called for each found "own property", and
// you don't need to do the instance.hasOwnProperty check any more
});
When you're using for (var key in obj) it will loop through the given object + its parent objects' properties on the prototype chain until it reaches the end of the chain. As you want to check only a specific object's properties, you need to use hasOwnProperty.
This is not needed in for (var i = 0; i < length; i++) or data.forEach().
YES, use it always with for ... in
There are some nice answers here describing what hasOwnProperty() does and offering other solutions.
But none do provide an answer to what this question and #João in comments asks.
Is this always required?
In other words,
if the object is mine, if I have control over it, if the object is defined as my own local variable,
do I still need to use hasOwnProperty()?
The complication with this question is, that the control over the variable of Object type is not what's important in this consideration.
What's important is the control over the Object type itself.
If the question is slightly rephrased to: "Is the use of hasOwnProperty() required if I have full control over the JS script, where it's used and everything in its or parent scopes?"
Then no, you don't need to use the hasOwnProperty().
But the full control over the environment is not something you should count on.
Consider this example
var variableCreatedByInocentUser = { amisane: 'yes' };
for (let key in variableCreatedByInocentUser) {
console.log(key +'? '+ variableCreatedByInocentUser[key]);
}
console.log('-----');
Object.prototype.amicrazy = 'yes, you redefined Object type';
for (let key in variableCreatedByInocentUser) {
console.log(key +'? '+ variableCreatedByInocentUser[key]);
}
console.log('-----');
for (let key in variableCreatedByInocentUser) {
if (!variableCreatedByInocentUser.hasOwnProperty(key)) { continue; }
console.log(key +'? '+ variableCreatedByInocentUser[key]);
}
It's fine to drop the hasOwnProperty() only until someone somewhere redefines the Object type.
Before or even after your script is started.
The effect is retroactive. Even if you declared your variable "using original Object type",
it does not work as expected in JS and the redefined Object type will also affect such variables created before.
Even though the redefining of base types is discouraged, it's being done in some frameworks.
Such framework could be included and introduced into your global scope and break your script.
There might also be a safety issue. The Object could be redefined with malicious intention, making your loops perform additional tasks.
If you want to follow good practices, you should always consider all possible scenarios, like that the code you're writing could be reused or inserted, or joined with another project.
Use hasOwnProperty() even when it might seem not necessary and wasteful.
hasOwnProperty expects the property name as a string.
When you call Test.hasOwnProperty(name) you are passing it the value of the name variable (which doesn't exist), just as it would if you wrote alert(name).
Every object descended from Object inherits the hasOwnProperty method. This method can be used to determine whether an object has the specified property as a direct property of that object;
If you create a regular javascript object using say var obj = {}; it will have the object prototype. Same goes for objects created using var obj = new MyClass(); Before Object.create was introduced there was no way around this. However nowadays it's possible to create an object with no prototype (respectively null as its prototype) using var obj = Object.create(null);.
Why is this important? What advantages does it bring? Are there any real world use cases?
It's a completely empty object (nothing inherited from any .prototype including Object.prototype), so you can be guaranteed that any property lookup will only succeed if the property was explicitly added to the object.
For example, if you want to store some data where you won't know the keys in advance, there's a possibility that a provided key will have the same name as a member of Object.prototype, and cause a bug.
In those cases, you need to do an explicit .hasOwnProperty() check to rule out unexpected inherited values. But if there's nothing inherited, your testing can be simplified to a if (key in my_object) { test, or perhaps a simple truthy test if (my_object[key]) { if appropriate.
Also, with no prototype chain, I would imagine that lookups of properties that turn out to not exist would be faster, since only the immediate object would need to be checked. Whether or not this pans out in reality (due to optimizations) would be determined with performance testing.
The only difference here between creating an object with {} and Object.create(null) is that the Object prototype will not be inherited from.
This means that any of the methods we typically assume we can call on any object will not exist, such as toString and valueOf. A list of these can be found here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype
From a performance perspective, creating an object simply by {} is actually much faster, so unless you specifically cannot have the functions under the Object prototype you should not create objects in that manner.
http://jsperf.com/null-vs-empty-object-performance
I was digging around the jQuery source code and I found that they use this little code snippet to detect if a JavaScript object is empty.
function isMyObjEmpty( obj ) {
var name;
for (name in obj ) {
return false;
}
return true;
}
Can someone explain to me why this works? I just don't understand why this would ever return true.
Why it works:
This uses a for... in loop to iterate through the object's properties.
If the object has any property, it would enter the loop and return false
If the object has no properties, it would not enter the loop, and return true.
Why it doesn't:
Note that there exists a case where it does not work. for.. in loops only go through enumerable properties so technically an object can be non-empty and it would still return false. One can define a property to not be enumerable and trick this method. Here is the problematic case.
The correct thing to say is that this method checks if an object has any enumerable properties.
What the docs say:
You can find the method's documentation here.
Description: Check to see if an object is empty (contains no enumerable properties).
I personally find it odd they would call that method isEmptyObject. I think a better suited name would be hasNoEnumerableProperties.
What if you really want to check if an Object is empty?
In newer implementations of JS one can use Object.getOwnPropertyNames. getOwnPropertyNames gets all the properties, enumerable or not.
You can implement isMyObjEmpty with Object.getOwnPropertyNames(myObject).length===0. This checks that the object has no properties, enumerable or not.
This however, does not check prototypical properties though. This might, or might not be desirable behavior, you can check the discussion I've had with theshadowmonkey about it. That could be easily solved by making a call to Object.getPrototypeOf recursively and checking for properties across the prototypical chain.
If it finds name in obj then there is something in the obj and it is not empty, if it cannot do that it will return true, saying the obj is empty
Try this. I think this is because of the object's own properties. You need to have hasOwnProperty to make sure you don't access its prototypes properties.
function isMyObjEmpty( obj ) {
var name;
for (name in obj ) {
if(obj.hasOwnProperty(name)) {
return false;
}
}
return true;
}
Read the document and see the implications written there.
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Statements/for...in
Maybe not, but I'm assuming that the confusion comes from the key "name" in obj. It's not actually looking for a key called name in the object, rather any keys in the object are being assigned to a variable that they have called name. therefore, if it finds anything in the object, it will return false and confirm that it is indeed not an empty object. But if it finds nothing in the object, it will return true meaning that your object is empty.
The key is that the for..in loop iterates over every property of the object, but nothing else. If there's nothing in the object at all, then that loop will never run, and so the "return false" line never gets executed. The program then moves on to the next line, which tells it to return true.
(This leads to an interesting question itself. Should that for..in loop be wrapped up in a hasOwnProperty() check? Or does the function actually intend to catch non-own properties and count the object as nonempty on that basis?)
When will it return true, when the object is empty of course.
isMyObjEmpty({});
how does it work? By using for...in
for...in
Summary
Iterates over the enumerable properties of an object, in arbitrary
order. For each distinct property, statements can be executed.
So if there are no properties, it will not go into the for in loop. The the loop really should be checking for hasOwnProperty() since that can lead to a false positive.
I don't know how to extend the map object with prototype and hope you can help.
I have something like this:
var map = {'one':1, 'two':2};
and I would like to have a method to check for the existence of a key:
if (map.containsKey('one')){...}
How would I extend the map object?
It's dangerous to modify Object.prototype, because it affects all objects and will usually break other libraries you may be using. In general, if you want to add methods to a dictionary-like object, you should create an object for your hash instances to inherit from, like the Prototype Hash object.
For this specific instance, you should really just use either if (key in map) or if (map.hasOwnProperty(key)).
There is already an operator to test the existence of a key inside an object.
(In JavaScript, objects are implemented as maps so actually there is no real map.)
if( 'one' in map )
{
alert(map['one']);
}
These are not "maps" they are objects. Building on Maurice's answer, if you want this to apply to all objects:
Object.prototype.containsKey = function(key) {
return this.hasOwnProperty(key);
};
The simplest way to do this is to add a function directly in the object:
map.containsKey = function(key) {
return this[key] ? true : false;
};
In Javascript, you do not need such method really.
if ( map['one'] ) {
// do something
}
should do it
As other's have said, extending Object.prototype might not be a good idea if your code has to play nice with code written by people ignorant of hasOwnProperty().
Anyway, there are three 'correct' ways I know of to check if a property is available:
obj.hasOwnProperty(name)
checks if a property with given name exists in the object.
name in obj
additionally includes properties inherited via an object's prototype chain.
typeof obj[name] !== 'undefined'
will additionally evaluate to false if the property is present but has been set to undefined.
Some non-JS object's (e.g. window.external in IE) might not implement hasOwnProperty(), so one of the other checks has to be used.