此article定义instanceof,如下所示:
instanceof运算符测试对象是否在其原型中 链接构造函数的prototype属性。
这是一个公平的解释和生活是好的,直到我从Eloquent Javascript书中看到这段代码:
function TextCell(text) {
this.text = text.split("\n");
}
TextCell.prototype.minWidth = function() {
return this.text.reduce(function(width, line) {
return Math.max(width, line.length);
}, 0);
}
TextCell.prototype.minHeight = function() {
return this.text.length;
}
TextCell.prototype.draw = function(width, height) {
var result = [];
for (var i = 0; i < height; i++) {
var line = this.text[i] || "";
result.push(line + repeat(" ", width - line.length));
}
return result;
}
function RTextCell(text) {
TextCell.call(this, text);
}
RTextCell.prototype = Object.create(TextCell.prototype);
RTextCell.prototype.draw = function(width, height) {
var result = [];
for (var i = 0; i < height; i++) {
var line = this.text[i] || "";
result.push(repeat(" ", width - line.length) + line);
}
return result;
};
&#13;
让我们创建一个RTextCell实例并执行以下c
var rt = new RTextCell("ABC");
console.log(rt instanceof RTextCell); // true
console.log(rt instanceof TextCell); // true
我理解为什么第二个console.log的输出是&#34; true&#34; - 因为构造函数TextCell是原型链的一部分。
然而,第一个console.log让我感到困惑。
如果查看代码(从下面开始的第10行),RTextCell的原型将更新为新的Object,其原型设置为TextCell.prototype。
RTextCell.prototype = Object.create(TextCell.prototype);
。
查看下面的快照,没有提到构造函数&#34; RTextCell&#34;在对象&#34; rt&#34;的原型链中。那么,按照我在帖子开头提到的定义,输出是否应该是假的?为什么它会返回真值?
我还阅读了this,但没有帮助我理解这个具体问题。
请按顺序查看rt,RTextCell,TextCell的快照。
答案 0 :(得分:4)
您确实更改了RTextCell.prototype
,但在构建任何RTextCell
实例之前更改了。考虑这个大不相同的示例,其中在使用原始原型创建实例后修改RTextCell.prototype
:
var rt = new RTextCell();
RTextCell.prototype = somethingTotallyDifferent;
rt instanceof RTextCell; // false!
创建rt
时,rt.__proto__ === RTextCell.prototype
为真。一旦RTextCell.prototype
发生变化,就会停止变为真。
如果rt
的原型链中的prototype
具有原始 RTextCell
属性,则您不会进行测试。相反,您正在测试对象的原型链中是否存在RTextCell.prototype
的值 。对RTextCell
个实例始终如此,因为RTextCell
构造函数创建的实例始终在其原型链中获取当前值RTextCell.prototype
,并且您永远不会更改RTextCell.prototype
你开始构建实例。
答案 1 :(得分:1)
wait
正在测试RTextCell.prototype是否存在于obj的原型链中。因为obj是使用新的RTextCell制作的。 RTextCell.prototype具有原型TextCell.prototype的事实就在这里,并且似乎在抛弃你。
obj instanceof RTextCell
没有摆脱RTextCell.prototype,它仍然是一个对象,但它的原型恰好是TextCell.prototype。
答案 2 :(得分:1)
确切的措辞很重要。你谈到原型链中的构造函数,但原始引用并没有:
instanceof运算符测试对象是否在其原型中 链接构造函数的原型属性。
所以表达式rt instanceof RTextCell
实际上正在测试这样的事情(请记住__proto__
不是标准的):
var p = rt.__proto__;
while(p)
{
if(p == RTextCell.prototype)
return true;
p = p.__proto__;
}
return false;
所以即使函数RTextCell
没有在上面的对象树中直接引用,RTextCell.prototype
对象也是。