# Class checking: "instanceof" The `instanceof` operator allows to check whether an object belongs to a certain class. It also takes inheritance into account. Such a check may be necessary in many cases, here we'll use it for building a *polymorphic* function, the one that treats arguments differently depending on their type. ## The instanceof operator [#ref-instanceof] The syntax is: ```js obj instanceof Class ``` It returns `true` if `obj` belongs to the `Class` (or a class inheriting from it). For instance: ```js run class Rabbit {} let rabbit = new Rabbit(); // is it an object of Rabbit class? *!* alert( rabbit instanceof Rabbit ); // true */!* ``` It also works with constructor functions: ```js run *!* // instead of class function Rabbit() {} */!* alert( new Rabbit() instanceof Rabbit ); // true ``` ...And with built-in classes like `Array`: ```js run let arr = [1, 2, 3]; alert( arr instanceof Array ); // true alert( arr instanceof Object ); // true ``` Please note that `arr` also belongs to the `Object` class. That's because `Array` prototypally inherits from `Object`. The `instanceof` operator examines the prototype chain for the check, and is also fine-tunable using the static method `Symbol.hasInstance`. The algorithm of `obj instanceof Class` works roughly as follows: 1. If there's a static method `Symbol.hasInstance`, then use it. Like this: ```js run // assume anything that canEat is an animal class Animal { static [Symbol.hasInstance](obj) { if (obj.canEat) return true; } } let obj = { canEat: true }; alert(obj instanceof Animal); // true: Animal[Symbol.hasInstance](obj) is called ``` 2. Most classes do not have `Symbol.hasInstance`. In that case, check if `Class.prototype` equals to one of prototypes in the `obj` prototype chain. In other words, compare: ```js obj.__proto__ === Class.prototype obj.__proto__.__proto__ === Class.prototype obj.__proto__.__proto__.__proto__ === Class.prototype ... ``` In the example above `Rabbit.prototype === rabbit.__proto__`, so that gives the answer immediately. In the case of an inheritance, `rabbit` is an instance of the parent class as well: ```js run class Animal {} class Rabbit extends Animal {} let rabbit = new Rabbit(); *!* alert(rabbit instanceof Animal); // true */!* // rabbit.__proto__ === Rabbit.prototype // rabbit.__proto__.__proto__ === Animal.prototype (match!) ``` Here's the illustration of what `rabbit instanceof Animal` compares with `Animal.prototype`: ![](instanceof.png) By the way, there's also a method [objA.isPrototypeOf(objB)](mdn:js/object/isPrototypeOf), that returns `true` if `objA` is somewhere in the chain of prototypes for `objB`. So the test of `obj instanceof Class` can be rephrased as `Class.prototype.isPrototypeOf(obj)`. That's funny, but the `Class` constructor itself does not participate in the check! Only the chain of prototypes and `Class.prototype` matters. That can lead to interesting consequences when `prototype` is changed. Like here: ```js run function Rabbit() {} let rabbit = new Rabbit(); // changed the prototype Rabbit.prototype = {}; // ...not a rabbit any more! *!* alert( rabbit instanceof Rabbit ); // false */!* ``` That's one of the reasons to avoid changing `prototype`. Just to keep safe. ## Bonus: Object toString for the type We already know that plain objects are converted to string as `[object Object]`: ```js run let obj = {}; alert(obj); // [object Object] alert(obj.toString()); // the same ``` That's their implementation of `toString`. But there's a hidden feature that makes `toString` actually much more powerful than that. We can use it as an extended `typeof` and an alternative for `instanceof`. Sounds strange? Indeed. Let's demystify. By [specification](https://tc39.github.io/ecma262/#sec-object.prototype.tostring), the built-in `toString` can be extracted from the object and executed in the context of any other value. And its result depends on that value. - For a number, it will be `[object Number]` - For a boolean, it will be `[object Boolean]` - For `null`: `[object Null]` - For `undefined`: `[object Undefined]` - For arrays: `[object Array]` - ...etc (customizable). Let's demonstrate: ```js run // copy toString method into a variable for convenience let objectToString = Object.prototype.toString; // what type is this? let arr = []; alert( objectToString.call(arr) ); // [object Array] ``` Here we used [call](mdn:js/function/call) as described in the chapter [](info:call-apply-decorators) to execute the function `objectToString` in the context `this=arr`. Internally, the `toString` algorithm examines `this` and returns the corresponding result. More examples: ```js run let s = Object.prototype.toString; alert( s.call(123) ); // [object Number] alert( s.call(null) ); // [object Null] alert( s.call(alert) ); // [object Function] ``` ### Symbol.toStringTag The behavior of Object `toString` can be customized using a special object property `Symbol.toStringTag`. For instance: ```js run let user = { [Symbol.toStringTag]: "User" }; alert( {}.toString.call(user) ); // [object User] ``` For most environment-specific objects, there is such a property. Here are few browser specific examples: ```js run // toStringTag for the envinronment-specific object and class: alert( window[Symbol.toStringTag]); // window alert( XMLHttpRequest.prototype[Symbol.toStringTag] ); // XMLHttpRequest alert( {}.toString.call(window) ); // [object Window] alert( {}.toString.call(new XMLHttpRequest()) ); // [object XMLHttpRequest] ``` As you can see, the result is exactly `Symbol.toStringTag` (if exists), wrapped into `[object ...]`. At the end we have "typeof on steroids" that not only works for primitive data types, but also for built-in objects and even can be customized. It can be used instead of `instanceof` for built-in objects when we want to get the type as a string rather than just to check. ## Summary Let's recap the type-checking methods that we know: | | works for | returns | |---------------|-------------|---------------| | `typeof` | primitives | string | | `{}.toString` | primitives, built-in objects, objects with `Symbol.toStringTag` | string | | `instanceof` | objects | true/false | As we can see, `{}.toString` is technically a "more advanced" `typeof`. And `instanceof` operator really shines when we are working with a class hierarchy and want to check for the class taking into account inheritance.