Class Checking "instanceof"
Classes: Class Checking
What is class checking in JavaScript?
View Answer:
Let's say we have a Car
class, and we want to confirm if a given object is an instance of Car
. Here's how we might perform class checking in JavaScript:
class Car {
constructor(model, year) {
this.model = model;
this.year = year;
}
}
// Create a new instance of Car
let myCar = new Car('Tesla Model 3', 2022);
// Check if myCar is an instance of Car
if (myCar instanceof Car) {
console.log('myCar is an instance of Car');
} else {
console.log('myCar is not an instance of Car');
}
In this example, myCar instanceof Car
will return true
because myCar
was created as an instance of the Car
class. So, the output of this code would be "myCar is an instance of Car".
This is a simple form of class checking. It is important to note that JavaScript is a prototype-based language, and class checking can become more complex when inheritance and other advanced features are used. But for most practical purposes, the instanceof
operator will serve you well.
What operator is typically used for class checking?
View Answer:
const myArray = [1, 2, 3, 4, 5];
console.log(myArray instanceof Array); // Returns true
What does the instanceof operator do in JavaScript?
View Answer:
class Car {
constructor(model, year) {
this.model = model;
this.year = year;
}
}
class Bike {
constructor(model, year) {
this.model = model;
this.year = year;
}
}
let myCar = new Car('Tesla Model 3', 2022);
let myBike = new Bike('Yamaha MT-15', 2020);
console.log(myCar instanceof Car); // Returns true
console.log(myCar instanceof Bike); // Returns false
console.log(myBike instanceof Car); // Returns false
console.log(myBike instanceof Bike); // Returns true
In this code:
myCar instanceof Car
checks ifmyCar
is an instance of theCar
class, and returnstrue
.myCar instanceof Bike
checks ifmyCar
is an instance of theBike
class, and returnsfalse
.myBike instanceof Car
checks ifmyBike
is an instance of theCar
class, and returnsfalse
.myBike instanceof Bike
checks ifmyBike
is an instance of theBike
class, and returnstrue
.
As you can see, instanceof
allows you to confirm the class of an object in JavaScript.
Is an Array an instance of an Object in JavaScript?
View Answer:
let myArray = [1, 2, 3, 4, 5];
console.log(myArray instanceof Array); // Returns true
console.log(myArray instanceof Object); // Also returns true
In this code:
myArray instanceof Array
checks ifmyArray
is an instance of theArray
class, and returnstrue
.myArray instanceof Object
checks ifmyArray
is an instance of theObject
class, and also returnstrue
.
As you can see, an Array is indeed considered an instance of an Object in JavaScript, due to JavaScript's object-based nature where almost everything is an object.
Is it possible to make a custom obj instanceof Class algorithm?
View Answer:
class MyCustomClass {
static [Symbol.hasInstance](instance) {
return Array.isArray(instance);
}
}
const myArray = [1, 2, 3, 4, 5];
const myObject = {foo: 'bar'};
console.log(myArray instanceof MyCustomClass); // Returns true
console.log(myObject instanceof MyCustomClass); // Returns false
In this code:
- We define a
MyCustomClass
class with aSymbol.hasInstance
method. - This method checks if the
instance
is an Array using theArray.isArray
method. myArray instanceof MyCustomClass
checks ifmyArray
is an "instance" ofMyCustomClass
as per our custom definition, and returnstrue
becausemyArray
is an array.myObject instanceof MyCustomClass
checks ifmyObject
is an "instance" ofMyCustomClass
as per our custom definition, and returnsfalse
becausemyObject
is not an array.
So, you can indeed customize the behavior of the instanceof
operator in modern JavaScript. Note that this can lead to some surprising results, so use this feature with caution!
Can you explain what happens with an instanceof class check?
View Answer:
class Rabbit extends Animal {}
let rabbit = new Rabbit();
console.log(rabbit instanceof Animal); // true
// rabbit.__proto__ === Rabbit.prototype
// rabbit.__proto__.__proto__ === Animal.prototype (match! return true)
We already know that plain objects are converted to string as [object Object]. Is there a way to create a custom toString result for our custom objects?
View Answer:
let user = {
[Symbol.toStringTag]: 'User',
};
console.log({}.toString.call(user)); // [object User]
// toStringTag for the environment-specific object and class:
console.log(window[Symbol.toStringTag]); // Window
console.log(XMLHttpRequest.prototype[Symbol.toStringTag]); // XMLHttpRequest
console.log({}.toString.call(window)); // [object Window]
console.log({}.toString.call(new XMLHttpRequest())); // [object XMLHttpRequest]
Is typeof operator useful for class checking?
View Answer:
Can you use instanceof with built-in JavaScript classes?
View Answer:
let myDate = new Date();
console.log(myDate instanceof Date); // Returns true
let myArray = [1, 2, 3];
console.log(myArray instanceof Array); // Returns true
What will instanceof return if the object is not of a specific class?
View Answer:
class MyClass {}
let myInstance = new MyClass();
let myNumber = 5;
console.log(myInstance instanceof MyClass); // logs true
console.log(myNumber instanceof MyClass); // logs false
Is instanceof reliable across different windows or frames?
View Answer:
Here's an example that illustrates the potential issue with instanceof
across different windows or frames.
// Assume we have two windows or frames: window1 and window2
let array1 = window1.Array;
let array2 = window2.Array;
let instance1 = new array1();
let instance2 = new array2();
console.log(instance1 instanceof array1); // logs true
console.log(instance2 instanceof array1); // logs false even though instance2 is an Array object
In this case, instance2
is an instance of Array
, but instanceof
returns false
because it's from a different window or frame.
What is a drawback of instanceof in Modern JavaScript?
View Answer:
The following example demonstrates this drawback of instanceof
. Consider two iframes, each with their own execution environment.
Assume we have two iframes with their separate JavaScript execution contexts:
<iframe id="iframe1" srcdoc="<script>window.onload = function() { parent.array1 = new Array(); };</script>"></iframe>
<iframe id="iframe2" srcdoc="<script>window.onload = function() { parent.array2 = new Array(); };</script>"></iframe>
Then in the parent frame:
window.onload = function() {
console.log(array1 instanceof Array); // logs true
console.log(array2 instanceof Array); // logs true
console.log(array1 instanceof array2.constructor); // logs false
}
In the above code, array1
and array2
are both instances of Array
, but array1 instanceof array2.constructor
returns false
because array1
and array2
were created in different execution contexts (iframes), each with its own Array
constructor.
How can you perform class checking across iframes in JavaScript?
View Answer:
Here is a simple code example. Instead of using instanceof
, you can use Object.prototype.toString.call()
to perform class checking across iframes:
<iframe id="iframe1" srcdoc="<script>window.onload = function() { parent.arrayFromIframe = new Array(); };</script>"></iframe>
<script>
window.onload = function() {
console.log(Object.prototype.toString.call(arrayFromIframe) === '[object Array]'); // logs true
}
</script>
In the above example, even though arrayFromIframe
was created in a different execution context (an iframe), Object.prototype.toString.call(arrayFromIframe)
still correctly identifies it as an Array.
What would Object.prototype.toString.call() return for an array?
View Answer:
What is duck typing in JavaScript?
View Answer:
let Duck = function() {};
Duck.prototype.quack = function() {
console.log('Quack!');
};
let NotADuck = function() {};
let duck = new Duck();
let notADuck = new NotADuck();
function makeItQuack(possiblyADuck) {
if (typeof possiblyADuck.quack === 'function') {
possiblyADuck.quack();
} else {
console.log('This is not a duck!');
}
}
makeItQuack(duck); // logs 'Quack!'
makeItQuack(notADuck); // logs 'This is not a duck!'
In this example, we don't care about the type of possiblyADuck
. We only care that it has a quack
method. This is the essence of duck typing: "If it quacks like a duck, it's a duck."
Can instanceof be used with custom classes?
View Answer:
How does instanceof differ from typeof?
View Answer:
class MyClass {}
let myInstance = new MyClass();
let myNumber = 5;
console.log(myInstance instanceof MyClass); // logs true
console.log(myNumber instanceof MyClass); // logs false
console.log(typeof myInstance); // logs "object"
console.log(typeof myNumber); // logs "number"
Why can't we rely on the constructor property for class checking?
View Answer:
function MyClass() {}
const myInstance = new MyClass();
console.log(myInstance.constructor === MyClass); // true
MyClass.prototype.constructor = null;
console.log(myInstance.constructor === MyClass); // false
const noConstructor = Object.create(null);
console.log(noConstructor.constructor); // undefined
This code demonstrates that relying on the constructor
property for class checking can be unreliable.
Can class checking be used to identify null or undefined values?
View Answer:
Does instanceof work with primitive types in JavaScript?
View Answer:
let myString = "Hello, World!";
let myNumber = 42;
console.log(myString instanceof String); // false
console.log(myNumber instanceof Number); // false
In both checks, instanceof
returns false
because these are not instances of String
or Number
objects, but primitive string and number types.
Is instanceof always accurate for arrays?
View Answer:
How would you perform class checking for null or undefined?
View Answer:
In JavaScript, you can use a direct comparison for checking null
or undefined
. Here's an example:
let myNullValue = null;
let myUndefinedValue = undefined;
console.log(myNullValue === null); // true
console.log(myUndefinedValue === undefined); // true
In this code, the ===
operator accurately checks if myNullValue
is null
and myUndefinedValue
is undefined
.