instanceof check works on subclass without setting constructor [duplicate]

空扰寡人 提交于 2019-12-01 20:46:07

问题


I have the following JavaScript code

function Parent() {
}

function Child() {
}

Child.prototype = Object.create(Parent.prototype);

Note the absence of the statement

Child.prototype.constructor = Child;

My understanding is that as the constructor property has not been set the instanceof checks should fail for new instances of Child class.

var child = new Child();
child instanceof Child; //Should give false

I verified that the constructor is incorrectly set

But when I run child instanceof Child it gave me true

But it should be false as constructor property is not set on Child's prototype to be Child.

Environment

Google Chrome Version 48.0.2564.109 (64-bit)
Ubuntu 14.04 LTS

回答1:


My understanding is that as the constructor property has not been set the instanceof checks should fail for new instances of Child class.

No, that's incorrect. In fact, until ES2015 (aka ES6), the constructor property wasn't used for anything at all in JavaScript itself. It was defined as existing on the default objects the runtime assigns to the prototype property on functions, but not used.

instanceof doesn't care about construtor at all. Consider:

o instanceof Foo

instanceof will look to see if the object Foo.prototype points to is anywhere on o's prototype chain. (If "prototype chain" is not a familiar term, see the * at the end of the answer and then come back.) If so, it returns true; if not, it returns false.

E.g., here's a conceptual implementaton of instanceof, hand-waving away some details:

function isAnInstance(obj, func) {
    var p;
    for (p = Object.getPrototypeOf(obj); p; p = Object.getPrototypeOf(p)) {
        if (p === func.prototype) {
            return true;
        }
    }
    return false;
}

Although it's been superceded by the ES2015 spec, I'll link to the ES5 spec because it's written in more accessible language and this aspect hasn't changed: instanceof effectively just calls a function's [[HasInstance]] internal method, defined here.

We can see that constructor isn't involved from your question, and also from this simple demonstration:

var p = {};
var o = Object.create(p);
var Foo = function() {};
Foo.prototype = p;
snippet.log(o instanceof Foo); // true
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="//tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

Note that:

  1. o wasn't created via Foo
  2. In fact, Foo didn't even exist until after o was created
  3. o and its prototype don't have a constructor property at all

...and yet instanceof says "Yep, looks like it's a Foo." :-) Purely because the object Foo.prototype points to is also on o's prototype chain.


* "prototype chain"

You clearly know that objects in JavaScript have prototypes from which they inherit properties. Those prototypes are objects, and so they have prototypes. So you get a "chain" of prototypes.

Consider a two-level (arguably three-level) inheritance hierarchy, here in ES5:

function Base() {
}

function Derived() {
    Base.call(this);
}
Derived.prototype = Object.create(Base.prototype);
Derived.prototype.constructor = Derived;

...or in ES2015:

class Base {
}
class Derived extends Base {
}

Now we use it:

var d = new Derived();

(Where you see "the d object" and similar in the below, I do of course mean "the object d refers to" — but that's really verbose.)

Now, the d object's prototype is Derived.prototype. Derived.prototype's prototype is Base.prototype. Base.prototype's prototype is Object.prototype. Object.prototype doesn't have a prototype (its [[Prototype]] internal slot is null).

Those objects are the prototype chain underlying d, and they mean that d is instanceof Object, instanceof Base, and instanceof Derived.



来源:https://stackoverflow.com/questions/35537995/instanceof-check-works-on-subclass-without-setting-constructor

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!