A foolproof method for confirming an object is an EcmaScript 6 Map or Set

Can someone help me verify if an object is a Map or Set, but not an Array?

For checking an Array, I currently use lodash's _.isArray.

function myFunc(arg) {
  if (_.isArray(arg)) {
    // doSomethingWithArray(arg)
  }

  if (isMap(arg)) {
    // doSomethingWithMap(arg)
  }

  if (isSet(arg)) {
    // doSomethingWithSet(arg)
  }
}

If I were to create the isMap/isSet functions, how should they be implemented? I want them to be able to handle subclasses of Map/Set if possible.

Answer №1

When it comes to detecting arrays accurately and reliably, the current situation resembles the pre-ES5 methods. Refer to this insightful article for a deeper understanding of the potential pitfalls of implementing isArray.

Various methods can be utilized:

  • obj.constructor == Map/Set, but this approach is ineffective with subclass instances and vulnerable to deception.
  • obj instanceof Map/Set, while functional, may fail across realms and can be tricked via prototype manipulation.
  • obj[Symbol.toStringTag] == "Map"/"Set", which can be easily deceived again.

To ensure accuracy, testing for [[MapData]]/[[SetData]] internal slots is necessary, although these are not easily accessible as they are internal. However, a workaround exists:

function isMap(o) {
    try {
        Map.prototype.has.call(o); // throws if o is not an object or has no [[MapData]]
        return true;
    } catch(e) {
        return false;
    }
}
function isSet(o) {
    try {
        Set.prototype.has.call(o); // throws if o is not an object or has no [[SetData]]
        return true;
    } catch(e) {
        return false;
    }
}

For general use, utilizing instanceof is recommended for its simplicity, understandability, performance, and effectiveness in most scenarios. Alternatively, one could opt for duck typing and focus on whether the object possesses has/get/set/delete/add/delete methods.

Answer №2

To determine if an object is a Set, you can utilize the instanceof operator:

function checkIfSet(obj) {
  return obj instanceof Set;
}

If the object in question inherits the Set.prototype, the instanceof operator will return true.

update — Although the instanceof approach is effective in most cases, there are specific scenarios where it may not be accurate, as explained in Bergi's response.

Answer №3

To check if an item is a Map or Set, you can use the following functions:

export function isMap(item) {
  return !!item && Object.prototype.toString.call(item) === '[object Map]';
}

export function isSet(item) {
  return !!item && Object.prototype.toString.call(item) === '[object Set]';
}

It's important to note that these functions will work unless the prototype of this method has been overridden.

Answer №4

If you're looking for inspiration for your Vue code, check out this method used in the Vue source code. You can get some great ideas from here.

export const isMap = (val: unknown): val is Map<any, any> =>
  toTypeString(val) === '[object Map]'
export const isSet = (val: unknown): val is Set<any> =>
  toTypeString(val) === '[object Set]'


export const objectToString = Object.prototype.toString
export const toTypeString = (value: unknown): string =>
  objectToString.call(value)

It's a straightforward approach. Just convert the object to a string and then check if it matches '[object Map]' or '[object Set]'

I recommend frontend developers to explore the Utility functions in the Vue source code. There's always something valuable to learn.

Here is the link to Vue source: https://github.com/vuejs/vue-next/blob/master/packages/shared/src/index.ts

You can find the code I referenced here.

Answer №5

Alternatively, you can verify the prototypes:

Object.getPrototypeOf(i) === Map.prototype

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The error message "Unable to map props.theTodos" is displayed

I'm facing an error message while compiling: "TypeError: props.theTodos.map is not a function". I've been struggling with this issue for quite some time, but I haven't found a solution yet as I'm using hooks instead of class components. ...

What's the best way to retrieve the dates for the current week using JavaScript?

Could anyone help me find a way to retrieve the first and last dates of the current week? For example, for this week, it would be from September 4th to September 10th. I encountered an issue at the end of the month when dates overlap two months (such as t ...

Using environmental variables in Nuxt 3 outside of component setup scripts can be easily achieved by accessing the variables directly

I have stored different API URLs in my .env file, specifically for development and production environments. Here is how I access these URLs: const isProdEnv = process.env.NODE_ENV === 'production' const DEV_API_URL = "https://example-stage.h ...

What is the method to establish a reference based on a value in programming?

Having some trouble setting the 'ref' of a TextInput from a value. Here's an example: var testtest = 'testvalue' <TextInput ref=testtest autoCapitalize="none" autoCorrect={false} autoFocus={false} placeholderTextColor="#b8b8b ...

Angular-material's Md-dialog popup box is displayed as a separate view within the Yeoman framework

I have recently created a project using Yeoman (angular-fullstack, angular-material) and encountered an issue with triggering the md-dialog box. When clicking on a div element, the dialog box is supposed to appear. However, instead of showing the popup the ...

Ways to remove curly brackets from a dictionary?

Is there a way to remove the curly brackets (with ** around them) from my JSON response without messing up the entire Dictionary? If not, is it possible to assign key-values before the curly brackets (with ** around them) to access the values in the card k ...

Creating a personalized input slider: A step-by-step guide

I have a question about how to design a custom input slider with the label inside the field itself. The desired output should look like the screenshot below: https://i.sstatic.net/gE6EJ.png I have successfully created the input field part, but I am stru ...

What exactly is the purpose of editing a host file?

After reviewing this repository, an automatic message pops up: Don't forget to modify your host file 127.0.0.1 * http://localhost:3001 What exactly does that entail? ...

What is the method to retrieve the return value from this ajax request?

Here's a code snippet: var information = { ObtainInfo : function() { var url = 'http://www.bungie.net/api/reach/reachapijson.svc/game/info/'+storage.get('apikey'); $.ajax({ url: url, su ...

Offering fields for modules, main, and browser that meet the needs of ESM, CommonJS, and bundlers

I have upgraded a number of my published npm packages to include both commonjs and esm builds. Some of these packages are meant for use in both node and the browser, and they are all compiled using webpack or rollup. Additionally, all of them are written i ...

How can I adjust the column width in OfficeGen?

Currently, I am utilizing officeGen for the purpose of generating word documents. <sup> let table = [ [ { val: "TT", fontFamily: "Times New Roman", }, { val: "Ten hang", ...

How to automatically insert a page break after a certain string in an array using JavaScript

I've created a code that is intended to implement page breaks after a specific number of new lines or words. I have defined an array that indicates where these breaks should occur within my element. In the example provided in my jsFiddle, you can see ...

Using a JSON key as a parameter in a function

Would it be achievable to specify the key of an object as a function parameter? For instance, if I were to develop a filter function that could sort multiple map markers by marker.element.country or marker.element.population? This approach would allow me ...

Prevent users from clicking by using a CSS class in HTML and JavaScript

,hey there buddy 1° Can you help me figure out how to prevent click behavior using the CSS class? 2° I'm unable to add an ID to the HTML element, so I need to use the Class to achieve this. 3° None of my attempts have been successful so far. El ...

Is it possible to spread an empty array in JavaScript?

Whenever I run the code below, I encounter the error message Uncaught SyntaxError: expected expression, got '...': [1,2,3, (true ? 4 : ...[])] I'm wondering if spreading an empty array in that manner is allowed? ...

Is the absolute positioned element on the left or right based on its current location?

Is there a way to assign absolute positioning with left at 0px or right at 0px depending on whether the positioned div will go outside of its container? For example, when you right click in a browser and see the menu appear to the right of where you click ...

Exploring React and finding the way to a specific item

I have a list of users displayed in a table. When a user clicks on a row, I want to navigate to a different component to show the details. <tbody> {this.state.clients.map(client => ( <tr className="tableRow" onClick={() => this. ...

using the information from the child array within a v-if condition

I'm struggling to extract data from a child array and utilize it in my v-if condition. Below are my data and code. Any assistance would be appreciated, even if it's just pointers to the right documentation. <div class='post' v-for= ...

Tips for validating Angular form group input depending on the value of another input within the form?

I am facing an issue with form validation in my Angular version 8 application. I need to validate a form based on the following rules: If a file is uploaded (even if just clicking the button without selecting a file), then the Reason input is not required ...

Using jQuery AJAX to send data containing symbols

When making an AJAX call, I am including multiple values in the data like this: var postData = "aid="+aid+"&lid="+lid+"&token="+token+"&count="+count+"&license="+license; postData = postData + "&category="+category+"&event_name="+e ...