All objects in JavaScript are instances of the root class Object. That
is, for any object o, o instanceof Object will be true (unless you
explicitly set its __proto__ property, which you should avoid). This
has little practical consequence to you; it’s primarily to provide
some important methods that all objects must have, such as
toString
, which is covered later in this chapter.
Enumerating Object Properties, Revisited
We’ve already seen how we can enumerate the properties in an object with
for...in
.
Now that we understand prototypal inheritance, we can fully appreciate the use of
hasOwnProperty
when enumerating the proprties of an object. For an object
obj
and
a property
x
,
obj.hasOwnProperty(x)
will return
true
if
obj
has the property
x
, and
false
if the property isn’t defined or is defined in the prototype chain.
If you use ES6 classes as they’re intended to be used, data properties will always be
defined on instances, not in the prototype chain. However, because there’s nothing to
prevent adding properties directly to the prototype, it’s always best to use
hasOwnProp
erty
to be sure. Consider this example:
class
Super
{
constructor
() {
this
.
name
=
'Super'
;
this
.
isSuper
=
true
;
}
}
// this is valid, but not a good idea...
Super
.
prototype
.
sneaky
=
'not recommended!'
;
class
Sub
extends
Super
{
constructor
() {
super
();
this
.
name
=
'Sub'
;
this
.
isSub
=
true
;
}
}
const
obj
=
new
Sub
();
for
(
let
p
in
obj
) {
console.log(
`
${
p
}
:
${
obj
[
p
]
}
`
+
(
obj
.
hasOwnProperty
(
p
)
?
''
:
' (inherited)'
));
}
If you run this program, you will see:
158 | Chapter 9: Objects and Object-Oriented Programming