Welcome, fellow coders! In this blog, we’ll see how to check if an Object is a Map or a Set in JS. Shall we?
Checking for a Map
Method 1: Checking for a Map
The instanceof
operator checks if an object is an instance of a particular constructor function. In the case of Maps, it verifies if the object is an instance of the native Map constructor.
const myMap = new Map();
if (myMap instanceof Map) {
console.log("It's a Map!"); // Output: It's a Map!
}
Explanation:
- Behind the scenes,
instanceof
examines the prototype chain. It checks if the prototype property of the constructor appears anywhere in the prototype chain of the object. - For Maps, the prototype property of the Map constructor is checked against the prototype chain of
myMap
. - If
myMap
is indeed an instance of Map, the condition evaluates to true.
⚠ Common Gotcha:
Extending the Map class can lead to unexpected results. When extending, the instanceof
check might yield true for both the parent and child classes.
class CustomMap extends Map {}
const myCustomMap = new CustomMap();
if (myCustomMap instanceof Map) {
console.log("It's a Map!"); // Output: It's a Map!
} else {
console.log("Oops, it's not a Map!"); // This might be unexpected
}
In this example, even though myCustomMap
is an instance of CustomMap
, the instanceof
check incorrectly evaluates to true for both CustomMap
and Map
.
Method 2: Duck Typing – If It Quacks Like a Map 🦆
Duck typing involves checking for the presence of specific properties or methods rather than a direct object type. For Maps, we can check if the object has essential Map methods.
function isMap(map) {
if (
map &&
typeof map.clear === 'function' &&
typeof map.delete === 'function' &&
typeof map.get === 'function' &&
typeof map.has === 'function' &&
typeof map.set === 'function'
) {
return true;
}
return false;
}
// Class duck typed on Map
const duckMap= {
clear: () => {},
delete: () => {},
get: () => {},
has: () => {},
set: () => {},
};
console.log(isMap(duckMap)); // Output: true
Explanation:
- The
isMap
function checks for existence essential map methods like:set
,clear
,delete
,get
, andhas
. - This guards against false positives that might arise from objects with methods having the same name but differing in functionality.
- This approach focuses on the behavior of the object rather than its class.
⚠ Common Gotchas:
Duck typing can produce false positives if an object has the same methods as a Map but isn’t a Map. Carefully consider the specific methods needed for accurate identification.
⚠ False Positives
function isMap(obj) {
return typeof obj === 'object' && typeof obj.set === 'function';
}
const fakeMap = { set: () => console.log("Fake set method") };
console.log(isMap(fakeMap)); // Output: true (Uh-oh!)
Here, fakeMap has a set method, tricking the duck typing check into classifying it as a Map, leading to a false positive.
⚠ Insufficient Checks
function isMap(map) {
if (
map &&
typeof map.clear === 'function' &&
typeof map.delete === 'function' &&
typeof map.get === 'function' &&
typeof map.set === 'function'
) {
return true;
}
return false;
}
const notQuiteMap = {
clear: () => console.log("Clearing something"),
delete: () => console.log("Deleting something"),
set: () => console.log("Setting something"),
};
console.log(isMap(notQuiteMap)); // Output: true (But it's not a Map!)
In this example, the isMap
function checks for the presence of the clear
, delet
e, get
, and set
methods to determine if an object behaves like a Map
. However, this check is insufficient because it overlooks the critical has
method, which is fundamental to Map behavior.
Checking for a Set
Method 1: Using instanceof
Similar to checking for a Map, instanceof
verifies if the object is an instance of the native Set constructor.
const mySet = new Set();
if (mySet instanceof Set) {
console.log("It's a Set!"); // Output: It's a Set!
}
Explanation:
- The
instanceof
operator performs a prototype chain check, ensuring that the prototype property of the Set constructor is present in the prototype chain ofmySet
. - If
mySet
is indeed an instance of Set, the condition evaluates to true.
⚠ Common Gotcha:
Similar to the Map example, if you extend the Set class, the instanceof
check may incorrectly evaluate to true for both the extended class and the Set class, leading to unexpected results.
class CustomSet extends Set {}
const myCustomSet = new CustomSet();
if (myCustomSet instanceof Set) {
console.log("It's a Set!"); // Output: It's a Set!
} else {
console.log("Oops, it's not a Set!"); // This might be unexpected
}
Method 2: Duck Typing – If It Quacks Like a Set 🦆
Duck typing involves checking for the presence of specific properties or methods rather than a direct object type. For Sets, we can check if the object has essential Set methods.
function isSet(set) {
if (
set &&
typeof set.add === 'function' &&
typeof set.clear === 'function' &&
typeof set.delete === 'function' &&
typeof set.has === 'function'
) {
return true;
}
return false;
}
const duckSet= {
add: () => {},
clear: () => {},
delete: () => {},
has: () => {},
};
console.log(isSet(duckSet)); // Output: true
Explanation:
- The isSet function checks for existence essential map methods like:
add
,clear
,delete
, andhas
. - This guards against false positives that might arise from objects with methods having the same name but differing in functionality.
- This approach focuses on the behavior of the object rather than its class.
⚠ Common Gotchas:
Duck typing can produce false positives if an object has the same methods as a Set but isn’t a Set. Carefully consider the specific methods needed for accurate identification.
⚠ False Positives
function isSet(obj) {
return (
obj &&
typeof obj.add === 'function' &&
typeof obj.clear === 'function' &&
typeof obj.delete === 'function' &&
typeof obj.has === 'function'
);
}
const fakeSet = { add: () => console.log("Fake add method") };
console.log(isSet(fakeSet)); // Output: true (Uh-oh!)
Just like the Map example, duck typing may lead to false positives if an object has methods with the same names as Set methods but lacks the expected functionality.
⚠ Insufficient Checks
function isSet(obj) {
return (
obj &&
typeof obj.add === 'function' &&
typeof obj.clear === 'function' &&
typeof obj.delete === 'function'
);
}
const notQuiteSet = { add: () => console.log("Adding something") };
console.log(isSet(notQuiteSet)); // Output: true (But it's not a Set!)
Insufficient duck typing checks may result in false positives, as demonstrated here. The object lacks the has
method, yet it passes the check.
🧪Practice Coding Problem: The Cartographer’s Dilemma
In the spirit of Test Driven Development ( 😁), lets test our understanding by solving a problem.
Your task is to implement a function named
cartographersDilemma
that takes anobject
(collection) as a parameter and solves the Cartographer’s Dilemma by determining whether it represents a Map, a Set, or neither. The function should return a string indicating the type of the collection.JavaScript/** * Solve the Cartographer's Dilemma by identifying the type of collection (Map, Set, or Neither). * @param {Object} collection - The collection to identify. * @returns {string} - The type of collection ('Map', 'Set', or 'Neither'). */ function cartographersDilemma(collection) { // > > > 👉 Write code here 👈 < < < } // Test Cases const mapInstance = new Map(); console.log(cartographersDilemma(mapInstance)); // Output: 'Map' const setInstance = new Set(); console.log(cartographersDilemma(setInstance)); // Output: 'Set' const plainObject = { key: 'value' }; console.log(cartographersDilemma(plainObject)); // Output: 'Neither'
Please attempt before seeing the Answer:
function cartographersDilemma(collection) {
if (collection instanceof Map) {
return 'Map';
} else if (collection instanceof Set) {
return 'Set';
} else {
return 'Neither';
}
}
Explanation:
- The cartographersDilemma function uses the instanceof operator to check whether the collection is an instance of the Map or Set constructor.
- If collection is an instance of Map, it returns ‘Map’. If it’s an instance of Set, it returns ‘Set’.
- If collection is not an instance of either Map or Set, the function returns ‘Neither’.
- Test cases in question, demonstrate the usage of the function with instances of Map, Set, and a plain object.
Now you can easily discern Maps and Sets objects in Javascript. And whether you use instanceof
or duck typing, you are now aware of the edge cases involved too.
Keep coding 🚀!