1

I'm trying to test if the following strings are arrow functions by regex testing it for the presence of =>. Here are my test cases. I've bolded the cases that should find a match - in other words, they're valid arrow functions.

  • name => '=>'
  • (name) => {...}
  • name => ({..})
  • function() { return '=>'; }
  • function(name) { return () => {}} - while this function has a valid arrow function inside of it, the function expression itself is not an arrow function
  • (name, age) => doSomething('ff')
  • name => doSomething(() => {})

My attempt is partially working, but needs a more knowledgeable eye.

(=>)\s*(?![^\{]*\})

Why am I doing this?

Arrow functions don't have their own context, the context is inherited from where they're defined, and so I can't set the context manually as I would with a normal function. I'm building an api, where a part of the api acts as an initializer for an object being instantiated. Just as a constructor gives one access to this, this initializer function will do the same and will depend on the initializer being a function expressions rather than an arrow function. I'd like to throw an exception and notify the user accordingly if they pass an arrow function as an argument.

bflemi3
  • 6,698
  • 20
  • 88
  • 155
  • 5
    You need a parser. There is a JS parser, implemented in JS and easy to use. Look at esprima.org. – Tomalak Jun 19 '17 at 18:26
  • So your starting point is a function, not a string, and then you're getting the string version and applying your regex to see if it's an arrow function? – T.J. Crowder Jun 19 '17 at 18:26
  • 2
    https://stackoverflow.com/questions/28222228/javascript-es6-test-for-arrow-function-built-in-function-regular-function –  Jun 19 '17 at 18:27
  • @T.J.Crowder Yes in the real implementation, the starting point is a function that I `toString()`, but that was unnecessary fluff for my question. – bflemi3 Jun 19 '17 at 18:29
  • @Tomalak I looked at acorn but for what I need that's overkill – bflemi3 Jun 19 '17 at 18:29
  • Why the downvote? – bflemi3 Jun 19 '17 at 18:31
  • 1
    Regexes are really bad at recursion, and javascript allows recursion. If you are searching your codebase then the example you've got is probably good enough and you can manually filter out the false positives. If you are writing something to validate user input automatically, then you need a proper parser. – JDB Jun 19 '17 at 18:31
  • 2
    See also [Regular Expressions: Now You Have Two Problems](https://blog.codinghorror.com/regular-expressions-now-you-have-two-problems/) – JDB Jun 19 '17 at 18:32
  • 3
    That's not a good argument. Regexes are inherently incapable of parsing source code. This applies to HTML just as it applies to JavaScript. You can't argue that using the wrong tool is better because using the right tool would be overkill. If the right tool is fast and available for free, doubly so. – Tomalak Jun 19 '17 at 18:36
  • @Jhoverit That's not as accurate as testing for `=>`... what about `Math.min` etc. See https://codedump.io/share/s3I2PMpKVrcg/1/javascript-es6-test-for-arrow-function-built-in-function-regular-function – bflemi3 Jun 19 '17 at 18:36
  • 1
    @Tomalak You're assuming you know what I'm using this for. Can we just stick to answering the question? – bflemi3 Jun 19 '17 at 18:37
  • You won't be stupid enough to try this check on any native code... Forget the answers about some native functions being different. –  Jun 19 '17 at 18:37
  • 6
    This seems like a typical [XY problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). What do you really want to achieve that? Why do you need to test whether a function is an arrow f.? Is it part of an API (of a library)? – idmean Jun 19 '17 at 18:38
  • 1
    *"...but that was unnecessary fluff for my question."* Not at all: It tells us that you're starting with a string that does, in some way, define a function, as opposed to total nonsense. That's a big distinction. – T.J. Crowder Jun 19 '17 at 18:38
  • 2
    Possible duplicate of [JavaScript ES6: Test for arrow function, built-in function, regular function?](https://stackoverflow.com/questions/28222228/javascript-es6-test-for-arrow-function-built-in-function-regular-function) –  Jun 19 '17 at 18:39
  • _deleting noise, this is just a dupe_ –  Jun 19 '17 at 18:41
  • @Jhoverit: Re `.prototype`: Neither do methods or bound functions, so that doesn't really tell you much. – T.J. Crowder Jun 19 '17 at 18:42
  • 5
    Because sometimes the question is wrong. And in cases where someone tries to parse arbitrary source code with regex, the question is always wrong. "stick to what was asked" is an indefensible position. If you know how to do it, you don't need to ask. If you need to ask, be prepared to be told that you are doing it wrong. – Tomalak Jun 19 '17 at 18:42
  • @Tomalak I'm not parsing "arbitrary" source code, my reasoning is sound. See question if you need an explanation. I'm asking for regex help, I don't help with javascript. – bflemi3 Jun 19 '17 at 18:54
  • 2
    It really makes no difference what you need it *for*. The point is that you try to analyze arbitrary source code with regex. – Tomalak Jun 19 '17 at 18:58
  • 1
    "*I'd like to throw an exception and notify the user accordingly if they pass an arrow function as an argument.*" - Don't. Never test on syntax, always test on behaviour. What if the user doesn't *want* to initialise anything? What if the user passes a function expression that doesn't use `this`? What if the user passes a bound function? If you want to force the user to do some initialisation, test for that - call the function and check whether a certain property on `this` is defined afterwards. You should not care how the user of the API accomplishes that (or not). – Bergi Jun 19 '17 at 19:54

1 Answers1

2

Based on your examples, it seems to me you are testing from the wrong end. Check if the beginning is an arrow function:

([a-zA-Z]\w*|\([a-zA-Z]\w*(,\s*[a-zA-Z]\w*)*\)) => 
NetMage
  • 26,163
  • 3
  • 34
  • 55
  • Didn't think of that. Thank you for the answer. – bflemi3 Jun 19 '17 at 19:31
  • Did you mean to anchor that to the start of the string? – Bergi Jun 19 '17 at 19:48
  • This doesn't match the totally valid arrow function `({prop}) => prop`. Whatever regex you come up with, I'll always be able to provide a counterexample. – Bergi Jun 19 '17 at 19:50
  • That's fine, but seems to me to be outside the scope of the original question. – NetMage Jun 19 '17 at 19:56
  • 1
    to allow for single letter argument names better change `\w+` to `\w*` in the expression above. – Semmel Sep 09 '17 at 21:21
  • And don't forget empty argument arrow functions (`let one = () => 1;`). My expression is now: `(\(\)|[a-zA-Z]\w*|\([a-zA-Z]\w*\s*(,\s*[a-zA-Z]\w*)*\))\s*=>` – Semmel Sep 10 '17 at 20:07