2

I was working on a JavaScript application and came over this weird behavior.
Can anyone please explain to me why

function BaseClass() {}
function ClassOne() { this.bar = "foo"; }
function ClassTwo() { this.foo = "bar"; }

var base = new BaseClass();
ClassOne.prototype = base;
ClassTwo.prototype = base;

var one = new ClassOne();
var two = new ClassTwo();
one instanceof ClassTwo && two instanceof ClassOne;
// The line above will return true, but i think it should return false,
// because obviously one is not an instance of ClassTwo!
Sense545
  • 494
  • 4
  • 14

1 Answers1

6

Both one and two have the same prototype (constructor BaseClass). Object.getPrototypeOf(one) === Object.getPrototypeOf(two).

Instead of "recycling" new BaseClass in base, use:

// var base = new BaseClass(); <-- No!
ClassOne.prototype = new BaseClass();
ClassTwo.prototype = new BaseClass();
Rob W
  • 341,306
  • 83
  • 791
  • 678
  • This is true, though T.J. Crowder answered a question the other day with an elaborate explanation of why that's not necessarily the best way of doing things. I'll see if I can find it. – Pointy Jun 18 '12 at 14:25
  • +1 Great answer. This is a very tricky problem to spot and has caught me out before! – chrisfrancis27 Jun 18 '12 at 14:25
  • Yes @RobW that's it. Also T.J's little library for the purpose looks excellent. – Pointy Jun 18 '12 at 14:32
  • Yes, i actually fixed my code into using a new BaseClass for each sub-class right after i noticed this problem. The linked post talked about functions defined on the prototype of the Base class not beeing inherited, which is a different problem to mine. – Sense545 Jun 19 '12 at 06:05
  • `Object.getPrototypeOf(one)` will indeed return the BaseClass instance, but this does not explain how the instanceof operator works. The question was not how to fix the problem, i figured that out myself before posting. The question was **why** instanceof works like this, or what instanceof actually does that makes it think one is an instance of ClassTwo. – Sense545 Jun 19 '12 at 06:24
  • 1
    @Sense545 See specfication: [The instanceof operator](http://es5.github.com/#x11.8.6), [[[HasInstance\]\]](http://es5.github.com/#x15.3.5.3): "If O and V refer to the same object, return true." (example: O=One.prototype, V=any prototype in the prototype chain of `ClassOne`). **Q**: "What makes instanceof think that one is an instanceof ClassTwo". A: `one` is an instance of `ClassOne`, whose prototype is identical to `ClassTwo`'s prototype. – Rob W Jun 19 '12 at 09:06