Let's consider the following code,
let f = function () { this.a = 1; this.b = 2; } let o = new f(); f.prototype.c = 3; console.log(Object.getPrototypeOf(o));
Prints
[object Object] { c: 3 }
But if I use setPrototypeOf instead of f.prototype.c, the object is empty.
let f = function () { this.a = 1; this.b = 2; } let o = new f(); Object.setPrototypeOf(f, {c: 3}); console.log(Object.getPrototypeOf(o));
Prints
[object Object] { ... }
But if I use
let f = function () { this.a = 1; this.b = 2; } let o = new f(); Object.setPrototypeOf(f, {c: 3}); console.log(Object.getPrototypeOf(f));
Prints
[object Object] { c: 3 }
In short the question is, when using Object.setPrototypeOf(o), the Object prints empty, and when using Object.setPrototypeOf(f), the objects prints the property which is added. where as when setting prototype using f.prototype.c = 3, it is accessible by both Objects prototype and the functions prototype.
When you Object.setPrototypeOf(f, ... )
, the chain is actually 3 long:
The prototype of o
is f
. The prototype of f
is {c:3}
.
So your examples are not equivalent to each other:
1) In the first example, you add the property c
directly to the prototype that instances of f
will use, so the proto of o
contains c
since f
is the constructor for o
.
In the last two examples you add c
to the proto of f
, so the prototype f
was created with. Remember that functions are also just objects and that you're setting the proto of a function you use as a constructor. So the proto of o
contains the proto of f
which contains c
.
2) In the 2nd example, you getPrototypeOf() o
. In the 3rd, you getPrototypeOf() f
. Hence only the 3rd example shows c
again.
3) If you inspect the element in chrome, you see that the constructor of the 2nd example is f
, since you ask the proto of o
.
In the 3rd example you'll see that the constructor is Object
, since you ask the proto of f
, which has been set to the object {c}
and skip the proto from o
to f
.
PS: I'm aware this is might be a confusing explanation.
PPS: If you want inheritance, sticking to child.prototype = Object.create( parent.prototype ); child.constructor = child;
child.prototype = Object.create( parent.prototype ); child.constructor = child;
or ES6 class class child extends parent
when it can be used led to the least confusion for me personally.
var first = function first() { this.value = 'first function'; }; // before .prototype.extra, first inherist from Function. console.log( 'constructor of first before:', first.constructor ); first.prototype.extra = 'implemented with .prototype.extra'; // after .prototype.extra, first still inherits from Function, we did not change anything to first itself. console.log( 'constructor of first after:', first.constructor ); // When first is used as a prototype, the instances will get "extra". // Aka, everything that inherist from first. var first_instance = new first(); console.log( 'extra on instance of first:', first_instance.extra ); // f itself does NOT have the extra property, only instances of first do. console.log( 'extra on first itself:', first.extra ); console.log( '------' ); var second = function second() { this.value = 'second function'; }; // before setPrototypeOf, second inherist from Function, like above. console.log( 'constructor of second before:', second.constructor ); Object.setPrototypeOf( second, { extra: 'implemented with .setPrototypeOf()' }); // after setPrototypeOf, second inherist from Object, we broke the default inheritance chain. console.log( 'constructor of second after:', second.constructor ); // BY doing this, we effectively turned second into an object. // It no longer is a function, so we cannot use function methods like .call() or .apply() console.log( 'second is object, not function: function.apply', second.apply ); console.log( 'second is object, not function: object.hasOwnProperty', second.hasOwnProperty ); // When second is used as a prototype, the instances will not get "extra". var second_instance = new second(); console.log( 'extra on instance of second:', second_instance.extra ); // second itself Does have the extra property, sine we assigned it on the prototype used by second. not when second is used as the prototype. console.log( 'extra on second itself:', second.extra );
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.