What Happened (Step-by-step)
var Foo = function(){};
A new function is defined, named - Foo. If we use console.dir(Foo)
we will see that Foo
has 2 special members prototype
and __proto__
Object.defineProperty(Foo.prototype,'x',{
get(){
return 3;
}
});
The prototype of Foo is updated. About defineProperty
(From MDN):
The static method Object.defineProperty() defines a new property
directly on an object, or modifies an existing property on an object,
and returns the object.
So the prototype
object is now modified with a new member named x
. The prototype
here acts as a c'tor and will "kick-off" when a new instance of Foo
will be created
var foo = new Foo();
A new instance of Foo is created. the c'tor call is using Foo prototype and x
getter is applied
Alternatives
Extending Foo prototype
, thus making sure it will effect only objects created from Foo
(as a class)
Object.defineProperty(Foo.prototype, 'x',
{
get: () => 3
});
console.dir(new Foo().x) // will show 3
console.dir(Foo.x) // undefined - protorype is for class objects
Or extending Foo __proto__
, thus updating Foo
as a function and while not affecting objectes created from it
Object.defineProperty(Foo.__proto__, 'x',
{
get: () => 3
});
console.dir(new Foo().x) // undefined - x is not a member of Foo
console.dir(Foo.x) // 3
Bonus: a very good article about JS prototypes and why this is happening
Original Answer
This is happening because in JS function
is a way to declare BOTH functions and classes!
So your Foo
function can be also used as a class
var Foo = function(){};
Foo(); // call Foo as a function
var obj = new Foo(); // initiate an instance from class Foo
Because you are using Foo.prototype
object (as a function) and then you create a new instance from your Foo
class you guarantee that:
- Your function prototype will be modified with your new getter
- Every new object (that inherits) from your class will also use your new getter (in object level)
I really think that your code should be something like this instead:
function Foo ()
{
Object.defineProperty(this,'x',{
get(){
return 3;
}
});
}