让我们考虑以下代码段:
function A() {}
var obj = new A();
function B() {};
obj.constructor = B;
console.info("1: ", obj.constructor); //Function B
console.info("2: ", obj instanceof A); //true
console.info("3: ", obj instanceof B); //false
我猜测是否和对象是某个函数类的实例,JS引擎必须检查对象是否具有相同的构造函数属性。但它似乎并没有发生,因为即使重写对象的构造函数属性也不会改变它的输出实例。
答案 0 :(得分:3)
ECMAScript 262规范将告诉您这一点。直接从其The `instanceof operator部分引用:
11.8.6 instanceof运算符
Shiftalpression的生产RelationalExpression:RelationalExpression实例的评估如下:
- 让lref成为评估RelationalExpression的结果。
- 让lval成为GetValue(lref)。
- 让rref成为评估ShiftExpression的结果。
- 让rval为GetValue(rref)。
- 如果Type(rval)不是Object,则抛出TypeError异常。
- 如果rval没有[[HasInstance]]内部方法,则抛出TypeError异常。
- 返回使用参数lval调用rval的[[HasInstance]]内部方法的结果。
醇>
至于[[HasInstance]]
是什么,规范还在其Object Internal Properties and Methods部分中将其定义为:
[[HasInstance]]
返回一个布尔值,指示参数是否可能是此对象构造的Object。在标准的内置ECMAScript对象中,只有Function对象实现[[HasInstance]]
进一步阅读:http://www.ecma-international.org/ecma-262/5.1/#sec-15.3.4.5.3
答案 1 :(得分:2)
这link个州:
instanceof运算符测试了constructor.prototype的存在 对象的原型链。
答案 2 :(得分:1)
(我现在回答了上一个问题确定的问题,这是here的副本,因此标记了这个CW。答案基本上只是这一个的副本,概括为a位。)
obj instanceof A
查看A.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 A() {}
function B() {
A.call(this);
}
B.prototype = Object.create(A.prototype);
B.prototype.constructor = B;
var obj = new B();
snippet.log(obj instanceof A); // true
snippet.log(obj instanceof B); // 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>
和A.prototype
引用的两个对象都在B.prototype
的原型链中。
obj
为真并不一定意味着instanceof
是通过直接或间接调用obj
创建的;它只是表明它们之间存在模糊的联系(A
指的是同样位于A.prototype
原型链中的对象)。 通常意味着obj
参与创建对象,但不能保证。
例如:
A
function A() {}
var obj = Object.create(A.prototype);
snippet.log(obj instanceof A); // true
请注意,根本没有调用<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
来创建对象。
或者可能更清楚和/或更显着:
A
function A() {}
var p = {};
var obj = Object.create(p);
snippet.log(obj instanceof A); // false
A.prototype = p;
snippet.log(obj instanceof A); // true
还有这个不寻常但完全可能的版本:
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
function A() {}
function B() {}
A.prototype = B.prototype = {};
var obj = new A();
snippet.log(obj instanceof B); // true
或者这个:
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
function A() {}
function B() {}
var obj = new B();
snippet.log(obj instanceof A); // false
A.prototype = B.prototype;
snippet.log(obj instanceof A); // true