Reputation: 39457
var ninja = {
name: 'Ninja',
say: function () {
return 'I am a ' + this.name;
}
};
function F(){
}
F.prototype = ninja;
var ninja2 = new F();
ninja2.name;
Output >>> "Ninja"
ninja2.constructor === F
Output >>> false
ninja2.constructor
Output >>> function Object()
ninja2.__proto__ === ninja
Output >>> true
In this example, why is not F
the constructor of ninja2
(as one would expect)?!
And I expect that because... the next example prints Hero
.
function Hero(){ }
var h1 = new Hero();
h1.constructor
Output >>> function Hero()
What is the conceptual difference?
I think it's related somehow to the fact that I set explicitly F.prototype = ninja;
in the first example. But how is it related to that? I am confused about this. Isn't F
the constructor of ninja2
? After all new F()
was used to create ninja2
?
Upvotes: -1
Views: 53
Reputation: 288120
The constructor
property has no magic, it's just a property that is automatically added when you create a function object:
13.2 Creating Function Objects
- Create a new native ECMAScript object and let F be that object.
- ...
- Let proto be the result of creating a new object as would be constructed by the expression
new Object()
whereObject
is the standard built-in constructor with that name.- Call the [[DefineOwnProperty]] internal method of proto with arguments "
constructor
", Property Descriptor {[[Value]]: F, { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true}, and false.- Call the [[DefineOwnProperty]] internal method of F with arguments "
prototype
", Property Descriptor {[[Value]]: proto, { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false}, and false.- ...
Example:
function F(){}
F.prototype.constructor; // F
Therefore, when you overwrite F.prototype
with another object, you lose the constructor
property.
Then, when you use ninja2.constructor
, you get Object
because:
ninja2
has no own constructor
property.ninja2
inherits from ninja
, which has no own constructor
property.ninja
inherits from Object.prototype
, which has an own constructor
property set to Object
.To fix this problem, you can
Restore constructor
in F.prototype
:
function F(){}
F.prototype = ninja;
F.prototype.constructor = F;
Include constructor
in ninja
:
var ninja = {
constructor: F, /* ... */
};
Add the desired properties to F.prototype
instead of replacing it with another object:
Object.assign(F.prototype, ninja); /* Requires ECMAScript 6 */
Upvotes: 2
Reputation: 79
You declare "F" as follows:
function F(){}
This will create a function object "F" with a prototype like this:
F.prototype = { constructor: F };
The "ninja" object you create has the Object() constructor by default. When you replace F.prototype with the "ninja" object, the following line of code now uses the Object() constructor from "ninja" because you overwrote F's prototype:
var ninja2 = new F();
Upvotes: 1