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不同的最佳方法是什么?
实际上如何工作?
解决方法
What is the best way to recognize that obj2 and obj3 are different?
这在很大程度上取决于你在做什么.一种方法是使用instanceof Obj2和instanceof Obj3.由于两个对象都是在原型链中使用Obj1.prototype创建的,因此它们确定为我们在基于类的OOP中称为超类型的实例.
How does actually instanceof work?
简短的版本
obj instanceof F查看F.prototype引用的对象是否在obj的原型链中的任何位置.它根本不使用构造函数.
更多细节
§11.8.5 – The instanceof Operator中的规范涵盖了这一点,它说(间接地,通过§8.6.2)它调用函数对象的[[HasInstance]]内部方法,传入我们正在测试的对象.函数[[HasInstance]](在§15.3.5.3中)表示它从函数的prototype属性获取对象引用,如果该对象在目标对象的原型链中的任何位置,则返回true,否则返回false.
它不使用构造函数(事实上,JavaScript本身没有) – 如果你考虑它,它就不能,因为一个对象的构造函数属性只能指向一个函数,但一个对象可以是多个函数的实例 – 例如,在伪经典继承的情况下:
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为true并不一定意味着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
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>