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

262 views Asked by At

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.

1

There are 1 answers

2
FZs On BEST ANSWER

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.