Comment vérifier de manière fiable un objet est un EcmaScript 6 Map / Set?

Je veux simplement vérifier qu'un objet soit une Map ou un Set et non un Array .

Pour vérifier un tableau, j'utilise le _.isArray de _.isArray .

 function myFunc(arg) { if (_.isArray(arg)) { // doSomethingWithArray(arg) } if (isMap(arg)) { // doSomethingWithMap(arg) } if (isSet(arg)) { // doSomethingWithSet(arg) } } 

Si je isMap mettre en œuvre isMap / isSet , à quoi ressemble-t-il? J'aimerais qu'il puisse attraper des sous-classes de Map / Set si possible aussi.

    La situation est similaire aux méthodes pré-ES5 pour détecter les tableaux correctement et de manière fiable. Voir cet article génial pour les éventuels pièges de la mise en œuvre d' isArray .

    On peut utiliser

    • obj.constructor == Map / Set , mais cela ne fonctionne pas sur les instances de la sous-classe (et peut facilement être trompé)
    • obj instanceof Map / Set , mais cela ne fonctionne toujours pas dans les domaines (et peut être trompé par le prototype de mangling)
    • obj[Symbol.toStringTag] == "Map" / "Set" , mais cela peut être trompé à nouveau.

    Pour être vraiment sûr, nous devrions tester si un objet possède une emplacement interne [[MapData]] / [[SetData]] . Ce qui n'est pas aussi facilement accessible – c'est interne. Nous pouvons utiliser un hack, cependant:

     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; } } 

    Pour une utilisation courante, je recommande l' instanceof – c'est simple, compréhensible, performant et fonctionne pour la plupart des cas raisonnables. Ou vous allez pour le canard de taper tout de suite et vérifiez seulement si l'objet has / get / set / delete / add / delete methods.

    Vous pouvez utiliser l' instanceof opérateur:

     function isSet(candidate) { return candidate instanceof Set; } 

    Si l'objet candidat possède Set.prototype dans sa chaîne prototype, l' instanceof opérateur renvoie true .

    Edit – tandis que l' instanceof chose fonctionnera la plupart du temps, il y a des situations où elle ne sera pas, comme décrit dans la réponse de Bergi.