title: new Function() constructor within loops/Array.map() in Javascript?
body: <h1>Update:</h1>
  <p>Since this has been closed without an answer I just want to make clear what that answer was thanks to a user below, and also provide the correct code in case anyone wants to use this.</p>
  <h3>Solution:</h3>
  <p>Per user @Bergi, <code>return</code> cannot be used within <code>Array.forEach()</code>.  Changing this to <code>for...of</code> solved the issue, though it was not immediately apparent to me, because I may have introduced another error into the code in the process of troubleshooting this.</p>
  <h3>Fixed Code:</h3>
  <p>The fixed code for this helper function, in case anyone finds this and wants to use it, is:</p>
  <pre class="lang-js prettyprint-override"><code>const makeConditional = (val, def = (val)=&gt; val, ...args) =&gt; {
    const conds = args.map(arg =&gt; {
          const c = new Function('i','return i' + arg.c);
          return {
              c: c,
              f: arg.f
          }
      });
  
      if (conds.length) {
          for (let cond of conds) {
              if (cond.c(val)) { return cond.f(val); }
          }
          return def(val);
      } else {
          return def(val);
      }
  }
  
  makeConditional(2, val=&gt;val+' is not a number', {c:'%2===0', f:val=&gt;val+' is even'},{c:'%2===1', f:val=&gt;val+' is odd'});
  // returns '2 is even'
  
  makeConditional(3, val=&gt;val+' is not a number', {c:'%2===0', f:val=&gt;val+' is even'},{c:'%2===1', f:val=&gt;val+' is odd'})
  // returns '3 is odd'
  
  makeConditional('test', val=&gt;val+' is not a number', {c:'%2===0', f:val=&gt;val+' is even'},{c:'%2===1', f:val=&gt;val+' is odd'})
  // returns 'test is not a number'
  
  makeConditional(49, val=&gt;val+' doesn\'t match any criteria', {c:'===0', f:val=&gt;val+' is zero'},{c:'===1', f:val=&gt;val+' is one'},{c:'%2===0', f:val=&gt;val+' is a multiple of 2'},{c:'%3===0', f:val=&gt;val+' is a multiple of 3'},{c:'%5===0', f:val=&gt;val+' is a multiple of 5'},{c:'%7===0', f:val=&gt;val+' is a multiple of 7'})
  // returns '49 is a multiple of 7'
  </code></pre>
  <h3>Epilogue:</h3>
  <p>I ended up deciding against using the new Function() constructor, even though I think it's slick to be able to pass conditional strings into the function, because passing a function allows for more flexibility. And it simplifies the code a lot. See below, for a more complex condition and function passed:</p>
  <pre class="lang-js prettyprint-override"><code>const makeConditional = (val, def = (val)=&gt; val, ...args) =&gt; {
      if (args.length) {
          for (let arg of args) {
              if (arg.c(val)) { return arg.f(val); }
          }
          return def(val);
      } else {
          return def(val);
      }
  }
  
  const iso8601Format = /^([0-9]{4})-?([01][0-9])-?([0-3][0-9])T([0-2][0-9]):?([0-5][0-9]):?([0-6][0-9])\.?(0{1,6})?(?:Z|(([+-])([01][0-9]):?([0-5][0-9])?))$/;
  
  makeConditional(
    '2020-12-09T15:20:30.000Z',
    (val) =&gt; `${val} is not a valid ISO-8601 date.`,
    {
      c: (i) =&gt; iso8601Format.test(i),
      f: (val) =&gt; {
        let [, year, month, day, hours, min, sec, fracSec, offset, offsetSign, offsetHours, offsetMin] = iso8601Format.exec(val) || [];
        return `${+day}/${+month}/${year}, at ${+hours}:${min}`;
      }
    }
  );
  // returns '9/12/2020, at 15:20'
  </code></pre>
  <hr />
  <h1>Original Post:</h1>
  <p>I am trying to write a function that creates custom conditional tests based on the args I put in, a helper function ultimately.</p>
  <p>I started with this test, which works great:</p>
  <pre class="lang-js prettyprint-override"><code>const makeConditional = (val, case1, case2, def) =&gt; {
      const c1 = new Function('i','return i'+case1.c);
      const c2 = new Function('i','return i'+case2.c);
      
      if (c1(val)) {
          return case1.f(val);
      } else if (c2(val)) {
          return case2.f(val)
      } else { 
          return def(val);
      }
  }
  
  makeConditional(2, {c:'%2===0', f:val=&gt;val+' is even'},{c:'%2===1', f:val=&gt;val+' is odd'}, val=&gt;val+' is not a number');
  // returns '2 is even'
  </code></pre>
  <p>As you can see, I pass test value, and then two objects, which consist of a conditional string that the test value will be tested against, and the functions to perform if the tests are successful, and finally a default function.  I use the &quot;new Function()&quot; constructor here, because the only other way to evaluate a string condition is with, eval(), which is is bad practice, and I wanted the 'purity' of passing in a pure string condition, as opposed to something like (i)=&gt;i%2===0, even though that'd work very well.  (this is my fallback option).  This is something only I will be using, so I could have gone with eval(), but I just think this is somehow nicer...</p>
  <p>OK, so having seen I could get this to work quite easily, I then tried to extrapolate this into letting the user (aka, me) pass as many conditions as I wanted, with the rest operator.</p>
  <pre class="lang-js prettyprint-override"><code>const makeConditional = (val, def = (val) =&gt; val, ...args) =&gt; {
    const conds = args.map(arg =&gt; {
      const c = new Function('i','return i' + arg.c);
      return {
        c: c,
        f: arg.f
      }
    });
  
    if (conds.length) {
      conds.forEach(cond =&gt; {
        if (cond.c(val)) { return cond.f(val); }
      });
      return def(val);
    } else {
      return def(val);
    }
  }
  
  makeConditional(2, {c:'%2===0', f:val=&gt;val+' is even'},{c:'%2===1', f:val=&gt;val+' is odd'}, val=&gt;val+' is not a number');
  // returns '2 is not a number, because conditional functions are never properly constructed, causing the function to return the default function passed'
  </code></pre>
  <p>So you can see here I put the 'default' function first, so I can use the rest operator with ...args to the map each argument to a new array that constructs a conditional function from the string 'c' in each given condition/case object, and then I loop through this new array, if it exists, returning if the given value meets the condition, or continuing the loop, and if no conditions match, or no arguments are given, the default/else function executes.  The default/else arg is also specified with a default function in case none is passed, which will just return the passed value.</p>
  <p><strong>However, this doesn't work.</strong>  Investigating what was going on I found that each 'c' conditional function (created by the new Function constructor) was not being created properly, as in the first test example.  Instead, Javascript seems to only accept the first argument, 'i', and not the second, in the constructor, and I believe this must have something to do with scope, but I don't understand why.   I tried refactoring the second function above to use a for...of loop instead of Array.map(), and got the same result.  It really seems to be the case that     you cannot use the new Function() constructor in any kind of loop or array iteration function.</p>
  <p>I would really like to do get this working using the new Function() constructor, instead of passing in a fully-formed conditional function, so please let me know if this is going to be possible.  If not I will just do it the other way.</p>
  <p>Thanks for your time.</p>