Script Preparation code:
x
 
function test(bin, bytes){
    var r, i;
    hex = '', chars = '\n: -';
    //generate an array of random octets and
    //a corresponding hex string
    for(i = 0; i < bytes; i++){
        r = Math.random() * 0x100 | 0,
        bin[i] = (r & 0xff);
        hex += (r >> 4).toString(16) + (r & 0xf).toString(16);
    }
    //insert non-hex characters at random positions in hex string
    for(i = 0; i < 10; i++){
        r = Math.random() * hex.length | 0;
        hex = hex.slice(0, r) + chars.charAt(r & 3) + hex.slice(r);
    }
  return hex;
}
var expected = [],
    testCase = test(expected, 10000);
function parseHex1(hex){// original
    hex = hex.replace(/[^0-9a-fA-F]/g, '');
    var i, 
        len = hex.length, 
        bin = [];
    for(i = 0; i < len - 1; i += 2){
        bin.push(+('0x' + hex.substring(i, i + 2)));
    }
    return bin;
}
function parseHex2(string) {// replace match map ES5
  return string.replace(/[^0-9a-fA-F]/g, '').match(/[0-9a-fA-F]{2}/g).map(function(hex) {
    return parseInt(hex, 16);
  });
}
function parseHex3(hex){//match without replace
        hex = hex.match(/[\da-f]/gi);
        for(var i = 0; i < hex.length - 1; i += 2){
            hex[i >> 1] = +('0x' + hex[i] + hex[i + 1]);
        }
        hex.length = i >> 1;
        return hex;
}
function parseHex4(hex){// iteration with replace
        var bin = [];
        hex.replace(/([\da-f])[^\da-f]*([\da-f])/gi,
            function(m, digit1, digit2){
                bin.push(+('0x' + digit1 + digit2));
            }
        );
        return bin;
}
function parseHex5(hex){// looping with exec
        var bin = [],
            regex = /([\da-f])[^\da-f]*([\da-f])/gi,
            result;
        while(result = regex.exec(hex)){
            bin.push(+('0x' + result[1] + result[2]));
        }
        return bin;
}
function parseHex6(hex){// non regex
    var bin = [], i, c, isEmpty = 1, buffer;
    for(i = 0; i < hex.length; i++){
        c = hex.charCodeAt(i);
        if(c > 47 && c < 58 || c > 64 && c < 71 || c > 96 && c < 103){
            buffer = buffer << 4 ^ (c > 64 ? c + 9 : c) & 15;
            if(isEmpty ^= 1){
                bin.push(buffer & 0xff);
            }
        }
    }
    return bin;
}
Tests:
  • original

     
    parseHex1(testCase);
  • ES5 replace match map

     
    parseHex2(testCase);
  • match without replace

     
    parseHex3(testCase);
  • iteration with replace

     
    parseHex4(testCase);
  • looping with exec

     
    parseHex5(testCase);
  • non regex

     
    parseHex6(testCase);
Rendered benchmark preparation results:

Suite status: <idle, ready to run>

Previous results

Experimental features:

  • Test case name Result
    original
    ES5 replace match map
    match without replace
    iteration with replace
    looping with exec
    non regex

    Fastest: N/A

    Slowest: N/A

Latest run results:
Run details: (Test run date: 7 months ago)
Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.7 Mobile/15E148 Safari/604.1
Mobile Safari 17 on iOS 17.7
View result in a separate tab
Test name Executions per second
original 2049.3 Ops/sec
ES5 replace match map 1033.9 Ops/sec
match without replace 1881.7 Ops/sec
iteration with replace 983.1 Ops/sec
looping with exec 1110.2 Ops/sec
non regex 6823.9 Ops/sec