EricSmekens / jsep

JavaScript Expression Parser
http://ericsmekens.github.io/jsep/
MIT License
836 stars 136 forks source link

Handling strings as numbers vs using regexp #136

Open LeaVerou opened 3 years ago

LeaVerou commented 3 years ago

In jsep, I've seen this pattern a lot:

// `ch` is a character code in the next three functions
let isDecimalDigit = function(ch) {
    return (ch >= 48 && ch <= 57); // 0...9
};

let isIdentifierStart = function(ch) {
    return  (ch >= 65 && ch <= 90) || // A...Z
            (ch >= 97 && ch <= 122) || // a...z
            (ch >= 128 && !binary_ops[String.fromCharCode(ch)]) || // any non-ASCII that is not an operator
            (additional_identifier_chars.hasOwnProperty(String.fromCharCode(ch))); // additional characters
};

let isIdentifierPart = function(ch) {
    return  (ch >= 65 && ch <= 90) || // A...Z
            (ch >= 97 && ch <= 122) || // a...z
            (ch >= 48 && ch <= 57) || // 0...9
            (ch >= 128 && !binary_ops[String.fromCharCode(ch)])|| // any non-ASCII that is not an operator
            (additional_identifier_chars.hasOwnProperty(String.fromCharCode(ch))); // additional characters
};

Is this done for performance? If not, it would be far easier to just do e.g. /^[A-Z0-9]$/i.test(str) instead of (ch >= 65 && ch <= 90) || (ch >= 97 && ch <= 122) || (ch >= 48 && ch <= 57), but I imagine there is a reason it wasn't done this way? We basically convert the string to a number before calling any of these functions, it's not like we even have the number in the first place. Could these be optimizations the compiler can already do with a well anchored regexp?

LeaVerou commented 3 years ago

Indeed it must be performance: I just wrote a quick benchmark and the regex version seems to be about 70% slower in every browser. OTOH we are talking about a roughly 15ms total difference in 1,300,000 comparisons, so still not sure it's worth it, but I can see the point now.