How can I see a Javascript object's prototype chain?
Given the following code:
function a() {}
function b() {}
b.prototype = new a();
var b1 = new b();
We can stay that a
has been added to b
's prototype chain. Great. And, all the following are true:
b1 instanceof b
b1 instanceof a
b1 instan开发者_运维百科ceof Object
My question is, what if we don't know the origins of b1
ahead of time? How can we discover the members of its prototype chain? Ideally I'd like an array like [b, a, Object]
or ["b", "a", "Object"]
.
Is this possible? I believe I've seen an answer somewhere on SO that described how to find out just this but I can't for the life of me find it again.
Well, the prototype link between objects ([[Prototype]]
) is internal, some implementations, like the Mozilla, expose it as obj.__proto__
.
The Object.getPrototypeOf
method of the ECMAScript 5th Edition is what you're needing, but it isn't implemented right now on most JavaScript engines.
Give a look to this implementation by John Resig, it has a pitfall, it relies on the constructor
property of engines that don't support __proto__
:
if ( typeof Object.getPrototypeOf !== "function" ) {
if ( typeof "test".__proto__ === "object" ) {
Object.getPrototypeOf = function(object){
return object.__proto__;
};
} else {
Object.getPrototypeOf = function(object){
// May break if the constructor has been tampered with
return object.constructor.prototype;
};
}
}
Remember that this is not 100% reliable, since the constructor
property is mutable on any object.
edit — This answer is from 2010, and quite obsolete. Since then the language has added the Object.getPrototypeOf()
API, which vastly simplifies the process.
You could use the "constructor" property of the object to find the prototype there, and then chain along that until you reached the end of the rainbow.
function getPrototypes(o) {
return (function gp(o, protos) {
var c = o.constructor;
if (c.prototype) {
protos.push(c.prototype);
return gp(c.prototype, protos);
}
return protos;
})(o, []);
}
(maybe) (or maybe not :-) give me a sec) (well crap; I think it's possible but ignore that code)
[edit] wow this is totally blowing my mind - that function's close but not quite right; setting up a chain of prototypes is weird and I'm feeling scared and lonely. I suggest paying attention only to the awesome @CMS above.
Another way to get the prototype chain:
function getPrototypeChain(obj) {
let prototypeChain = [];
(function innerRecursiveFunction(obj) {
let currentPrototype = (obj != null) ? Object.getPrototypeOf(obj) : null;
prototypeChain.push(currentPrototype);
if (currentPrototype != null) {
innerRecursiveFunction(currentPrototype);
}
})(obj);
return prototypeChain;
}
Here is a simple method without recursive function calls
function getProtoChain(o) {
const ans = []
let t = o
while (t) {
t = t.__proto__
ans.push(t)
}
return ans
}
Here is an example use of this function
class A {}
class B extends A {}
class C extends B {}
console.log(getProtoChain(new C())) // [C: {}, B: {}, A: {}, {}, null]
精彩评论