How does this function determine of an object is empty? - javascript

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.

Related

Array.length vs arrayinstance.length in javascript

I'm a bit confused by the Array.length property (i.e. a property named length on the Array function object) and array_instance.length (i.e. a property named length on instance of array object)
So what is difference between the two length property and when should/shouldn't we use them?
Edit 1:
there is also a length property on Array.prototype object. I am so confused.
Edit 2
Just to paint a clearer picture, here are the different length properties I have found
Edit 3
This is one of the follow up questions I asked in the comment section, but I think the question is important to fully understanding length property, so I have copy-pasted here in the main section
Follow up question:
Array.prototype.hasOwnProperty('length') and Array_instance.hasOwnProperty('length') return true, does that mean there are two length properties, one on array_instance, one on Array.prototype object, with the array_instance.length overshadowning the Array.prototype.length?
functions have a .length property which corresponds to how many arguments they are expecting. For example:
const unary = (a) => {
}
const binary = (a, b) => {
}
console.log(unary.length);
console.log(binary.length);
So the Array constructor has a length of 1 because it expects one parameter to be passed to it (namely, the size of the array).
array objects also have a .lengthproperty, which is unrelated other than having the same name. This property says how large the array currently is.
I really think a lot of the other answers have covered everything needed here, but as it seems the OP hasn't had what they see a a clear answer, I will try to set everything out, somewhat extensively - but as clearly as I can - in order to clarify. (Apologies if anyone thinks I am "stealing" their answer - I assure you that this is not the intention, and I'm deliberately not looking at them as I type this, but I've certainly read most of them and even upvoted a few.)
Array.length
This has already been well-covered above. Array is a native JS function, which you can use for creating arrays. It's less common then simply defining an array literal (and as far as I know there is no reason it would ever be preferable), but instead of var a = [1,2,3] you are allowed to do this:
var a = Array(1,2,3);
console.log(a);
Note in passing that you don't want to do this to create a singleton array, there is an utterly mad gotcha of a special case when you supply exactly one parameter which happens to be an integer:
var a = Array(5);
console.log(a);
Although that shows what appears to be an array of 5 undefined values in whatever JS console implementation SO uses, that's not actually quite what has been created (nor what is displayed in the current version of Chrome). I'm getting way off-topic but I'll refer you to Kyle Simpson's excellent walkthrough of the madness.
Anyway, since Array is a function, as others have already observed, it has a length property as all functions do. I'm really not sure why it evaluates to 1 though - for a user-defined function it is the number of arguments the function was formally declared with, but since Array like all native JS functions isn't actually implemented in JS, I couldn't tell you how the implementation actually works. Clearly it can take any number of arguments and thus is a rather "exotic" function. I don't think that Array.length would ever be useful, no matter what value was arbitrarily assigned to it, but it seems that most implementations go for 1, even if the specification leaves it open. (I'm not enough of a spec devotee to know if this is actually defined in there or left up to implementations.)
arrayinstance.length
This is just the feature of arrays that we know and use all the time. All JS arrays get this property - note that, although it is a property rather than a method (that is, it is not a function), it nevertheless "auto-updates" as the array gets longer/shorter:
var a = [1,2,3];
console.log(a.length);
a.push(4);
console.log(a.length);
a.pop();
a.pop();
console.log(a);
console.log(a.length);
Although as I said, Javascript's native constructors are not implemented in terms of JS itself, you could implement this kind of behaviour by defining a getter (at least since ES5).
Array.prototype.length
To fully explain what Array.prototype (and similar objects) is would take me deep into how Javascript's object system work. Suffice to say here that, unlike class-based languages (and JS does not have classes, even in ES6, despite the class syntax allowing us often to pretend it does), JS does not have the usual concept of "inheritance" that so-called OO languages do. In JS's version (sometimes called "prototypal inheritance"), what happens it that each object has an "internal prototype" which references some other object - and if you try to access a property on that object which it doesn't have, the JS engine will look at that "prototype object" for the property and use its value instead.
It's actually a very simple mechanism, but there are a number of things in the language which confuse this, one of them being the fact that functions (which are also objects) have a property called prototype - which does not point to the real "prototype" object which gets consulted if a nonexistent property is referenced on the function object. (A normal function foo has Function.prototype is the object that it delegates to - not foo.prototype.) However, if you declare a function foo, an object called foo.prototype is created - which is basically an empty, nondescript object. Its significance is that if the function foo is used as a "constructor" - that is, if you make an object by calling new foo() - foo.prototype will then be the object that JS will look up properties (including methods) on if any object constructed from foo happens to fail a property lookup.
This is why, at least in pre-ES6 code, you quite frequently saw this kind of pattern:
function foo(a,b) {
this.a = a;
this.b = b;
}
foo.prototype.add = function() {
this.a = this.a + this.b;
}
var myFoo = new foo(1,2);
console.log(myFoo.a);
myFoo.add();
console.log(myFoo.a);
myFoo.add();
console.log(myFoo.a);
console.log(myFoo.hasOwnProperty("add"));
Despite appearances, myFoo doesn't actually have a method add in this example - as confirmed by the final console.log. When the JS engine fails to find the property though, it goes to myFoo's "internal prototype", which happens to be foo.prototype. And that's why the method works, as it would on any object constructed from foo.
Anyway, this is leading up to the fact that Arrays, which could be (although almost never are) constructed by calling new Array (I didn't use the new operator above, but I could have done, this is a case where it makes no difference), therefore delegate to Array.prototype. All those array methods that you know and love don't "really" exist on the arrays you call them on:
var a = [1,2,3];
a.push(4);
console.log(a);
console.log(a.hasOwnProperty("push"));
console.log(Array.prototype.hasOwnProperty("push"));
So array methods only work because those methods are actually found on the Array.prototype object, to which all arrays delegate for property/method access if the lookup doesn't succeed on the array itself. (And this is why, if you look up any of them on MDN, the top of the page always says Array.prototype.<method_name>, because that's where the method "really" lives.)
A drastic demonstration of this (please DON'T do this in production code!)
// you're used to doing this, and it works:
[1,2].push(3);
console.log("that went fine");
// vandalism on a grand scale!
Array.prototype.push = undefined;
// now you can'tse the "push" method anymore!
[1,2,3].push(4);
But I'm going to end on something of an anticlimax. The above is true for array methods - but the length array property isn't a method. As observed above, it's just a "plain" (non-function) property, which "magically" behaves somewhat like a function call. As observed in the OP, .length property accesses don't delegate as the method calls shown above do, the property exists on each array in itself.
So why does Array.prototype still itself have a length property? Well, Array.prototype is actually itself an array. In fact, that's not the only thing:
Array.prototype.push(1);
console.log(Array.prototype);
Function.prototype();
notice that Array.prototype.push(1) ends up with Array.prototype being the singleton array [1]. So Array.prototype is "kind of like" the empty array (it's not exactly the same, because it has all those methods mentioned above directly accessible on the object itself, which a "normal" empty array doesn't). And with Function.prototype, although calling it didn't output anything, the fact that no TypeError was raised proves that it really is a function (it's actually a "no-op" function, like function() {}, but once again with various methods diretcly on it - the methods which every function has access to, such as .call and .bind).
Anyway, to cut the digression short, since Array.prototype is - as far as ordinary array properties are concerned, at least - an empty array, this explains why it has a length property, and why it's equal to 0.
I hope this clears things up, as well as demonstrating some of the more intriguing parts of Javascript.
The first part has already been answered, Array constructor is a function and functions have a .length property.
For the second, Array.prototype.length, it's a bit more obscur...
Array.prototype is actually an Array:
console.log(Array.isArray(Array.prototype)); // true
Array.prototype.push('hello');
console.log(Array.prototype.length); // 1
console.log(Array.prototype[0]); // "hello"
As to why is it an Array? Because specs say so:
The Array prototype object is an Array exotic objects and has the internal methods specified for such objects. It has a length property whose initial value is 0 and whose attributes are { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }..
There is also a note specifying that it is for compatibility reasons with previous versions of the specs.
As to why is was designed as being an Array? I have no really strong idea...
Disclaimer:
I have tried to show how constructor and instance works in general. But in fact, they have huge difference between different constructors.
Any constructor has been set its length with the value specified by the spec. Specially most of them are set to 1:
Number.length // 1
Object.length // 1
Function.length // 1
Array.length // 1
// etc.
Similarly,
Array.constructor.length // 1
// etc.
Like #Kaiido pointed out in the comment, you can see some constructor length is set:
Document.length // 0
Int8Array.length // 3
Date.length // 7
And you may also notice the length of the instance is undefined as they are not set. - It's out of the scope though.
let d = new Date
d.length === undefined // true
See at the bottom for relevant references.
But when you have an instance of it, then you're creating a new value of it:
typeof new Array === typeof Array.prototype // true
typeof new Function === typeof Function.prototype // true
// etc.
So, when you use an instance it has no length value set because it has no any parameters:
let arr = new Array // Array.prototype
arr.length === 0 // true
But when you use an instance with parameter, then you have the length property with the value of parameters
let arr = new Array(20)
arr.length === 20 // true
let func = function(a1,a2,a3,a4){}
func.length === 4 // true
// etc.
So now, you have been wondering why the constructor has length value equal to 1?
It's because the spec has set the value to be 1 initially.
Every built-in Function object, including constructors, has a length property whose value is an integer. Unless otherwise specified, this value is equal to the largest number of named arguments shown in the subclause headings for the function description, including optional parameters.
The value of the [[Prototype]] internal slot of the Object constructor is the intrinsic object %FunctionPrototype%.
Besides the length property (whose value is 1),
See these references:
Standard built in objects,
19.1.2 Properties of the Object Constructor,
19.2.2 Properties of the Function Constructor,
etc.
Also, you can see the prototype has length to 0, you already know it why in the preceding example.
Though, here's just a reference stating that:
19.2.3 Properties of the Function Prototype Object
And there some constructor whose length is set different. This is the out of scope of this answer. Though, here's a reference for the date constructor:
20.3.3 Properties of the Date Constructor
So, it's totally up to the spec how they have been defined.
Array.length
Array is constructor which means its type is "function". You try the checking it console.
typeof Array //"function"
According to MDN
The length property indicates the number of parameters expected by the function.
As the Array function expects single argument so Array.length = 0
array_instance.length
The length property of an object which is an instance of type Array sets or returns the number of elements in that array
As we know that arrays are actually objects so objects can have properties. The property length is on the instance of array.
Now second question you may ask why we don't get the length properties of array using Object.keys or for..in loop. The answer is because this property is not Enumerable.
let arr= [];
//this.property 'length2' will not be shown in for..in or Object.keys();
Object.defineProperty(arr,'length2',{
value:'length2 for test',
enumerable:false
})
//this property 'x' will be displayed in for..in loop and Object.keys()
Object.defineProperty(arr,'x',{
value:'length2 for test',
enumerable:true
})
console.log(Object.keys(arr)); //["x"]
Array.prototpe.length
According to the DOCS
The initial value of Array.prototype.constructor is the standard built-in Array
The Array prototype object is itself an array; its [[Class]] is "Array", and it has a length property (whose initial value is +0) constructor
Actually Array.prototype is an array. And remember array is always object. So it can have properties. The methods of the Array are stored in form of key:value. and there is no element in that array so it Array.prototype.length returns 0. If you push() some elements into it you will see it as array.
console.log(Array.prototype.length) //0
console.log(Array.isArray(Array.prototype)) //true
//adding element to array
Array.prototype.push('x')
console.log(Array.prototype.length) //1
As I explained in second parts you can hide properties of Object by setting enumerable:false. All the methods are keys of Array.prototype But now shown in for..in loops.
Array.length
For the number of properties in the array or the length property of an object which is an instance of type Array sets or returns the number of elements in that array.
Array.prototype.length
Inherited number of properties in the array. When you check Array.length you're actually checking Array.prototype.length

Javascript: Why is hasOwnProperty necessary? [duplicate]

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;

When do I need to use hasOwnProperty()?

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;

obj.hasOwnProperty(key) vs directly referencing using obj[key]

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.

Why Object.prototype looks like a empty object?

console.log(Object.prototype); // -> "{}"
I expected console.log(Object.prototype) to output some properties or mothods like "toString".
Why it doesn't?
The default methods are not marked as enumerable and thus not shown when viewing Object.prototype.
The reason for this is pretty simple: When viewing some object or more important iterating over its properties using for(var prop in object) you usually do not want to see any of the default methods. Of course one could always use a obj.hasOwnProperty(prop) check in such a loop but it's incredibly comfortable not having to do this by knowing that there's nothing enumerable on Object.prototype by default (and good code doesn't add enumerable properties to it either).

Categories

Resources