5

I am writing a function that returns true if the argument passed to it is an instance of a JavaScript Map.

As you may have guessed typeof new Map() returns the string object and we don't get a handy Map.isMap method.

Here is what I have so far:

function isMap(v) {
  return typeof Map !== 'undefined' &&
    // gaurd for maps that were created in another window context
    Map.prototype.toString.call(v) === '[object Map]' ||
    // gaurd against toString being overridden
    v instanceof Map;
}

(function test() {
  const map = new Map();

  write(isMap(map));

  Map.prototype.toString = function myToString() {
    return 'something else';
  };

  write(isMap(map));
}());

function write(value) {
  document.write(`${value}<br />`);
}

So far so good, but when testing maps between frames and when toString() has been overridden, isMap fails (I do understand why).

For Example:

<iframe id="testFrame"></iframe>
<script>
  const testWindow = document.querySelector('#testFrame').contentWindow;
  // false when toString is overridden 
  write(isMap(new testWindow.Map())); 
</script>

Here is a full Code Pen Demonstrating the issue

Is there a way to write the isMap function so that it will return true when both toString is overridden and the map object originates from another frame?

robbmj
  • 16,085
  • 8
  • 38
  • 63
  • 1
    @Bergi, how is this a duplicate? Your answer advocates using `instanceof` my question states the issue I am having with `instanceof` also the internal method you are checking on the set, does not apply to the `Map` prototype (i think). – robbmj Oct 10 '16 at 16:10
  • It's exactly the same for sets and maps. I guess I'll better edit the answer to be canonical. – Bergi Oct 10 '16 at 16:11
  • @Bergi please see the above edit, to my comment. – robbmj Oct 10 '16 at 16:12
  • See [my edit](http://stackoverflow.com/posts/29926193/revisions) there :-) You can use the other approaches if you don't like `instanceof` - and supporting `Map` instead of `Set` is just a choice of the right name. – Bergi Oct 10 '16 at 16:18
  • Note, this question is being discussed on [Meta](http://meta.stackoverflow.com/q/336008/215552). – Heretic Monkey Oct 10 '16 at 16:52

1 Answers1

5

You can check Object.prototype.toString.call(new testWindow.Map).

If that has been overridden, you're probably out of luck.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • Interesting, I hadn't though of that. I guess it does add one extra step of certainty. – robbmj Oct 10 '16 at 15:58
  • 1
    I wouldn't worry about `toString` being overridden (you can cache it if you come first), but rather about `Symbol.toStringTag`. – Bergi Oct 10 '16 at 16:10