const varRegex = /:([a-zA-Z][a-zA-Z0-9]*)/g; function Route(template) { this.pack = function pack(data) { const varRegexClone = new RegExp(varRegex); return template.replace(varRegex, function (m) { const key = varRegexClone.exec(m)[1]; varRegexClone.lastIndex = 0; // resetting regex object return data[key]; }); }; this.unpack = function unpack(str) { const regex = new RegExp(template.replace(varRegex, '([a-z0-9]+)')); const match = regex.exec(str); if (!match) { return null; } const vars = []; while (true) { const m = varRegex.exec(template); if (!m) { break; } vars.push(m[1]); } return _.zipObject(vars, match.splice(1)); }; } const r = new Route('/path/:param1/:param2/'); console.log(r.pack({param1: 'aaa', param2: 1234}); console.log(r.unpack('/path/bbb/5678/');