在下面的代码示例中,最后使用 instanceof 检查obj2和obj3,即使构造的方式不同,返回 name 的结果也会返回true财产是不同的。
var Obj1 = function() {
this.name = "foo1";
};
Obj1.prototype.name = "foo1onProt";
var obj1 = new Obj1();
var Obj2 = function() {};
Obj2.prototype = new Obj1();
Obj2.prototype.constructor = Obj2;
var obj2 = new Obj2();
var Obj3 = function() {};
Obj3.prototype = Object.create(Obj1.prototype);
Obj3.prototype.constructor = Obj3;
var obj3 = new Obj3();
console.dir(obj1);
console.log("obj1.name: " + obj1.name);
console.dir(obj2);
console.log("obj2.name: " + obj2.name);
console.dir(obj3);
console.log("obj3.name: " + obj3.name);
console.log("obj2 instanceof Obj1: " + (obj2 instanceof Obj1));
console.log("obj3 instanceof Obj1: " + (obj3 instanceof Obj1));
在Chrome中运行的结果:
Obj1
name: "foo1"
__proto__: Object
constructor: function () {
name: "foo1onProt"
__proto__: Object
obj1.name: foo1
Obj2
__proto__: Obj1
constructor: function () {}
name: "foo1"
__proto__: Object
constructor: function () {
name: "foo1onProt"
__proto__: Object
obj2.name: foo1
Obj3
__proto__: Object
constructor: function () {}
__proto__: Object
constructor: function () {
name: "foo1onProt"
__proto__: Object
obj3.name: foo1onProt
obj2 instanceof Obj1: true
obj3 instanceof Obj1: true
识别 obj2 和 obj3 的最佳方式是什么? 实际上 instanceof 是如何工作的?
答案 0 :(得分:16)
认识到obj2和obj3不同的最佳方法是什么?
这在很大程度上取决于你在做什么。一种方法是使用instanceof Obj2
和instanceof Obj3
。由于这两个对象都是在原型链中使用Obj1.prototype
创建的,因此它们确定为我们在基于类的OOP中称为超类型的实例。
实际上如何工作?
obj instanceof F
查看F.prototype
引用的对象是否位于obj
原型链中的任何位置。它根本不使用constructor
。
这在§11.8.5 - The instanceof Operator的规范中有所说明,它(间接地,通过§8.6.2)说它调用了函数对象的[[HasInstance]]
内部方法,传入了我们的对象重新测试。 Function
的{{1}}(在§15.3.5.3中)表示它从函数的[[HasInstance]]
属性获取对象引用,如果该对象在任何位置,则返回prototype
目标对象的原型链true
,如果没有。
它不使用false
(实际上JavaScript中没有任何东西) - 如果你考虑它,它就不能,因为对象的constructor
属性只能指向一个函数,但一个对象可以是constructor
多个函数 - 例如,在伪经典继承的情况下:
instanceof
function F1() {}
function F2() {
F1.call(this);
}
F2.prototype = Object.create(F1.prototype);
F2.prototype.constructor = F2;
var obj = new F2();
snippet.log(obj instanceof F1); // true
snippet.log(obj instanceof F2); // true
两者都是正确的,因为<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
和F1.prototype
引用的两个对象都在F2.prototype
的原型链中。
obj
为真并不一定意味着instanceof
是通过直接或间接调用obj
创建的;它只是表明它们之间存在模糊的联系(F
指的是同样位于F.prototype
原型链中的对象)。 通常意味着obj
参与创建对象,但不能保证。
例如:
F
function F() {}
var obj = Object.create(F.prototype);
snippet.log(obj instanceof F); // true
请注意,根本没有调用<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
来创建对象。
或者可能更清楚和/或更显着:
F
function F() {}
var p = {};
var obj = Object.create(p);
snippet.log(obj instanceof F); // false
F.prototype = p;
snippet.log(obj instanceof F); // true
还有这个不寻常但完全可能的版本:
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
function F1() {}
function F2() {}
F1.prototype = F2.prototype = {};
var obj = new F1();
snippet.log(obj instanceof F2); // true
或者这个:
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
function F1() {}
function F2() {}
var obj = new F2();
snippet.log(obj instanceof F1); // false
F1.prototype = F2.prototype;
snippet.log(obj instanceof F1); // true
答案 1 :(得分:2)
最简单:当obj instanceof constructor
在其构造函数/原型链中具有true
原型时,obj
会产生constructor
。换句话说,您询问引擎是否可以将obj
视为constructor
的实例/ obj
是否与constructor
对象相似。
有一些语法允许您将constructor
的原型放在obj
的原型链中。任何和所有这些都会导致obj instanceof constructor
成为true
。在您的示例中,obj2
和obj3
在其原型链中都有Obj1
。
因此,当您向javascript引擎询问 obj2
或obj3
是否与Obj1
的实例相似时,JavaScript会假设true
- - 唯一的情况是他们不会超越Obj1
的行为。