-1

Does this function definitely detect support of @@toStringTag sefely in any environment?

function hasToStringTagSymbol() {
    if (Symbol && (typeof Symbol() == "symbol") && !!Symbol.toStringTag) {
        var xTest = function () { };
        xTest.prototype[Symbol.toStringTag] = "Test";
        xTest = new xTest();
        return toString.call(xTest) == "[object Test]";
    }
    else {
        return false;
    }
}
Max Koretskyi
  • 101,079
  • 60
  • 333
  • 488
Andrey Godyaev
  • 856
  • 1
  • 8
  • 18
  • You could write a test for each scenario you expect to catch? – Nope Oct 19 '17 at 14:55
  • There are browsers that dont sypport ecmascript, so i have to detect if it is possible to use this symbol. – Andrey Godyaev Oct 19 '17 at 15:01
  • `delete Symbol` before your test, would that not simulate it not being present? – Nope Oct 19 '17 at 15:07
  • Feature detection example: https://stackoverflow.com/questions/29046635/javascript-es6-cross-browser-detection – Nope Oct 19 '17 at 15:14
  • 1
    The question possibly results from wrong premises. If browsers don't support ES6, the one should start with polyfill installation. Symbol and toString can be easily polyfilled. If you're after specific ES6 functions in your app, it may be better to focus on those that cannot be polyfilled, at least in old browsers. – Estus Flask Oct 19 '17 at 16:03
  • @estus Before main script is loaded i detect if feature is present, if not then polyfill runs . – Andrey Godyaev Oct 19 '17 at 16:57
  • @AndreyGodyaev This is how core-js works. If you don't want to reinvent the wheel, you can just use it, unless you're unhappy with its detection algos (it will force a polyfill if the feature is present but not compliant to the specs) – Estus Flask Oct 19 '17 at 17:12

1 Answers1

1

This piece of code doesn't detect properly polyfilled Symbol.toStringTag. While it is possible to polyfill Symbol and its effect on toString (this is done by core-js in particular), it's impossible to introduce new primitive type for typeof. The code above doesn't test that Symbol is a function as well (and it doesn't really need to create a new symbol).

It should be more like:

if (typeof Symbol !== "undefined" && Symbol && Symbol.toStringTag) {
    var o = {};
    o[Symbol.toStringTag] = "Test";
    return toString.call(o) == "[object Test]";
}

Symbol and its effect on toString can be easily polyfilled. If a developer is after specific JS features in the app, it may be better to focus on those that cannot be polyfilled, at least in old browsers. It can be Object.setPrototypeOf for ES5, Proxy for ES6 or the detection of syntactic features.

Estus Flask
  • 206,104
  • 70
  • 425
  • 565