Cycymomo
8/26/2013 - 7:34 AM

execMultiple.js

console.log(extractTagNamesES5('<a> and <b> or <c>'));  // [ 'a', 'b', 'c' ]

// If exec() is invoked on a regular expression whose flag /g is set
// then the regular expression is abused as an iterator:
// Its property `lastIndex` tracks how far along the iteration is
// and must be reset. It also means that the regular expression can’t be frozen.
var regexES5 = /<(.*?)>/g;
function extractTagNamesES5(str) {
    regexES5.lastIndex = 0;  // to be safe
    var results = [];
    while (true) {
        var match = regexES5.exec(str);
        if (!match) break;
        results.push(match[1]);
    }
    return results;
}

// If we had a method `execMultiple()` that returns an iterable,
// the above code would become simpler in ES6.
const REGEX_ES6 = /<(.*?)>/;  // no need to set flag /g
function extractTagNamesES6a(str) {
    let results = [];
    for (let match of REGEX_ES6.execMultiple(str)) {
         results.push(match[1]);
    }
    return results;
}

// Even shorter:
function extractTagNamesES6b(str) {
    return Array.from(REGEX_ES6.execMultiple(str), x => x[1]);
}

// Shorter yet:
function extractTagNamesES6c(str) {
    return [ for (x of REGEX_ES6.execMultiple(str)) x[1] ];
}