我写了一个名为protoDepth
的函数来计算对象原型链的深度:
function protoDepth(obj) {
var depth = 0
, proto
while (proto = Object.getPrototypeOf(obj)) {
obj = proto
depth++
}
return depth
}
然后我为这个函数写了一个测试,它出乎意料地失败了:
describe('`protoDepth`:', function() {
function A() {}
function B() {}
var a, b
beforeEach(function() {
a = new A
B.prototype = a
b = new B
})
it('provides the correct prototype depth.', function() {
expect(protoDepth(b)).toBe(2)
})
})
我预计深度为2
;也就是说,我认为depth++
只会被执行两次:
depth
是0
b
的原型是a
;深度为1
a
的原型是Object
;深度为2
Object
的原型是null
;故事的结尾。但这是错误的。 a
的原型似乎是a
。这是第一行执行的本地范围:
这里发生了什么?为什么A是__proto__
?由于我没有设置A.prototype
,默认情况下不是Object
吗?
答案 0 :(得分:1)
这就是B
的原型应该如何设置:
B.prototype = Object.create(A.prototype);
B.prototype.constructor = B;
现在,结果是3,因为原型链包含:B.prototype
,A.prototype
和Object.prototype
。
小提琴here(我添加了一些console.log
调用来显示结果),调试器现在显示:
B {constructor: function}
__proto__: B
constructor: function B() { }
__proto__: A
constructor: function A() { }
__proto__: Object
答案 1 :(得分:1)
由于我没有设置
A.prototype
,默认情况下不是对象吗?
不,默认情况下它是一个空对象(与function A
一起创建)。因此,b
的原型链是a
(== B.prototype
),然后是A.prototype
,然后是Object.prototype
,然后是null
。