My understanding is that the Object.hasOwnProperty
method checks if the object has a property name of it's own, meaning a non-inherited property. That would mean that the function should return false whenever the property a. doesn't exist, or b. if it's inherited.
Correct me if I'm wrong, but unless this doesn't use classical inheritance, doesn't bar
inherit from Foo
in the code below? Why is the hasOwnProperty
method returning true when the propname
property is an inherited property? What did I get wrong here?
Also, how would I use the hasOwnProperty
on the Foo
object? The code here returns false
when checking the the Foo
object.
function Foo() {
this.propname = 'test';
}
var bar = new Foo();
console.log(bar.hasOwnProperty('propname')); // returns true
console.log(Foo.hasOwnProperty('propname')); // returns false
My understanding is that the Object.hasOwnProperty
method checks if the object has a property name of it's own, meaning a non-inherited property. That would mean that the function should return false whenever the property a. doesn't exist, or b. if it's inherited.
Correct me if I'm wrong, but unless this doesn't use classical inheritance, doesn't bar
inherit from Foo
in the code below? Why is the hasOwnProperty
method returning true when the propname
property is an inherited property? What did I get wrong here?
Also, how would I use the hasOwnProperty
on the Foo
object? The code here returns false
when checking the the Foo
object.
function Foo() {
this.propname = 'test';
}
var bar = new Foo();
console.log(bar.hasOwnProperty('propname')); // returns true
console.log(Foo.hasOwnProperty('propname')); // returns false
Share
Improve this question
edited Apr 12, 2015 at 9:04
thefourtheye
240k53 gold badges465 silver badges500 bronze badges
asked Apr 12, 2015 at 9:03
shmulishmuli
5,1926 gold badges35 silver badges64 bronze badges
4
- The this on line 2 === bar, no prototype properties are set here. Add prototype ones by setting Foo.prototype.propname = ... – Douglas Commented Apr 12, 2015 at 9:07
- 1 Bar is an instance of Foo, rather than a descendant. – joews Commented Apr 12, 2015 at 9:07
- @Douglas can you please elaborate? Why does this require a prototype at all? The method is checking up the property... – shmuli Commented Apr 12, 2015 at 9:13
- 1 I've elaborated a bit in an answer below, but the point is that 'propname' is not an inherited property, the prototype needs to get involved somewhere for there to be inherited properties. – Douglas Commented Apr 12, 2015 at 9:20
5 Answers
Reset to default 5The stumbling point here is that Javascript uses prototypal inheritance. What you're seeing there isn't actually inheritance at all.
hasOwnProperty
will return false
if the property:
- Does not exist.
- Exists but only on the prototype chain.
The 'class' in your code is nothing to do with inheritance at all, it's just a function which sets some properties on an object.
That object happens to be an instance of a new empty object, because you called the function with the new
keyword, which is probably where the confusion is ing from.
Imagine rewriting the function as this:
function foo() {
var bar = {};
bar.propname = 'test';
return bar;
}
var baz = foo();
Would you expect baz.hasOwnProperty('propname')
to return true? Absolutely, because we explicitly defined the property on the object.
The alternative way to declare the property would have been to declare it on Foo
's prototype.
function Foo() {
this.bar = 'baz';
}
Foo.prototype.propname = 'test';
var baz = new Foo();
baz.propname; // 'test'
baz.hasOwnProperty('propname'); // false
Again, the magical stuff happening here is all down to the new
keyword. When you call a function with new
the function assigns the value of this
to be a new object and sets the prototype of that object to be the same as the prototype of the function you are calling.
Maybe the easiest way of explaining this is that there is a hasOwnProperty
method on bar
, but if you call bar.hasOwnProperty('hasOwnProperty')
it will return false
.
This is because the hasOwnProperty
method lives at the very top of the prototype chain, on Object.prototype
. Every object in Javascript inherits from here, which is why every object will have a hasOwnProperty
method.
There's a good article on why new
makes object oriented programming difficult in Javascript.
The initial code sample is equivalent to:
function Foo() {
}
var bar = new Foo();
bar.propname = 'test';
console.log(bar.hasOwnProperty('propname')); // returns true
console.log(Foo.hasOwnProperty('propname')); // returns false
This is why bar.hasOwnProperty('propname')
returns true (the property has been explicitly set on the bar object), and Foo.hasOwnProperty('propname')
returns false (the property has not been set on Foo at all, neither on the Foo object itself nor the prototype).
The hasOwnProperty
check is normally used like this:
function Foo() {
this.propname = 'test';
}
Foo.prototype.inheritedprop = 'test';
var bar = new Foo();
console.log(bar.hasOwnProperty('propname')); // returns true
console.log(bar.hasOwnProperty('inheritedprop')); // returns false
No, propname
is actually set on the instance of Foo
that is created by new
, based on Foo.prototype
(that is this
). Another approximation of the constructor pattern makes it clear(er) what is going on:
var FooPrototype = {};
var bar = Object.create(FooPrototype);
bar.propname = "test";
When you first wrote Foo, you simply defined a function to be used later.
The "bar" instantiates that function and essentially activates everything inside of it.
Check out this fiddle with these console.logs
console.log(Foo)
console.log(bar)
https://jsfiddle/7pzwcrjo/
You first have to instantiate a new object of the Foo class.
This JS bin further illustrates that point: http://jsbin./zaredowive/2/edit?js,console,output
As you can see the constructor is only called when you instantiate a new object of class Foo which in this case is a variable called bar. You are calling the hasOwnProperty on the function Foo. This function holds no properties.