I've been experimenting with JavaScript's world-renowned prototypical inheritance implementation. So far, everything makes sense to me except for one thing...
function base() {
this.a = "baseObj property";
}
base.thisIs = "base constructor";
function derived() {
this.b = "derivedObj property";
}
derived.thisIs = "derived constructor";
var baseObj = new base();
So far so good. baseObj.a
returns "baseObj property" and baseObj.constructor.thisIs
returns "base constructor".
But things begin to confuse me when I actually make something inherit the base object's values.
derived.prototype = baseObj;
derivedObj = new derived();
What ends up happening, is derivedObj.a
returns "baseObj property". Good. derivedObj.b
returns "derivedObj property". Good again. But derivedObj.constructor.thisIs
returns "base constructor"...
For this to be happening, the interpreter must be failing to find derivedObj.constructor
in derivedObj
. So what it does, is it follows derivedObj.__proto__
to search there instead. Because the new
keyword sets derivedObj.__proto__
equal to derived.prototype
, which we set earlier to equal baseObj
, derivedObj.__proto__
ends up returning baseObj
.
This would explain why derivedObj.constructor
has been forgotten about. It's seemingly useless. Interpreters don't need to use it to obtain derived.prototype
; they can just use derivedObj.__proto__
. The reality however, is that it could have been useful to use derivedObj.constructor
in order to obtain the value of derived.thisIs
.
But even after all that. It doesn't explain why it hasn't been forgotten in baseObj
. Why does a .constructor
exist within baseObj
but not derivedObj
? They were initialized the exact same way. With the new
keyword.
By default, functions have a prototype
property, which is the object from which the instances inherit when the function is used as a constructor. That prototype
object has a constructor
property, which points back to the function.
The problem with derived.prototype = baseObj
is that you replace the entire prototype
, so you lose the original derived.prototype.constructor
, which returned derived
.
A way to solve it would be reassigning that property:
derived.prototype = baseObj;
derived.prototype.constructor = derived;
However, that will alter the baseObj
object. This is usually undesired, so the proper way is
derived.prototype = Object.create(baseObj);
derived.prototype.constructor = derived;
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加