Search code examples
javascriptecmascript-5es5-compatiblity

What are the risks of using toString to get the name of a function?


Since ES5 doesn't support Function#name. I was looking for a way to emulate that functionality. While a lot of people recommend using Function#toString, others strongly advised against it.

So what are the risks of using the below code to get the name of a function?

if (!Object.hasOwnProperty(Function.prototype, "name")) {
  Object.defineProperty(Function.prototype, "name", {
    configurable: false,
    enumerable: true,
    get: function() {
      var result = /function\s+([^\s(]+)/.exec(this.toString());
      return result ? result[1] : "";
    }
  });
}

Since ES5 doesn't support arrow functions, I don't really see when the where the risk lies.


Solution

  • As the ECMAScript 5.1 specification says, the toString method returns a string that has the syntax of FunctionDeclaration:

    Function.prototype.toString ( )

    An implementation-dependent representation of the function is returned. This representation has the syntax of a FunctionDeclaration. Note in particular that the use and placement of white space, line terminators, and semicolons within the representation String is implementation-dependent.

    The toString function is not generic; it throws a TypeError exception if its this value is not a Function object. Therefore, it cannot be transferred to other kinds of objects for use as a method.

    FunctionDeclaration has the following syntax:

    FunctionDeclaration :

    function Identifier ( FormalParameterListopt ) { FunctionBody }

    FormalParameterList :

    Identifier
    FormalParameterList , Identifier

    And Identifier defined like:

    Identifier ::

    IdentifierName but not ReservedWord

    IdentifierName ::

    IdentifierStart
    IdentifierName IdentifierPart

    IdentifierStart ::

    UnicodeLetter
    $
    _
    \ UnicodeEscapeSequence

    IdentifierPart ::

    IdentifierStart
    UnicodeCombiningMark
    UnicodeDigit
    UnicodeConnectorPunctuation

    Conclusion

    Although it isn't a beautiful way to get the function name (but the only way in ES5), if you make it parse all of the possibilities listed above, it can work safely in ES5.

    But the ES6 standard modified the specifications for .toString(), which implies more possible syntaxes, making it unsafe to use this method in it.

    So, use this method only in versions prior to ES6.