前两天写那个异步函数顺序执行的过程中,动态修改函数,遇到setTimeout,我需要提取执行的时间,形如:
setTimeout(function() { output.innerText += '第三个异步函数,延迟1秒执行\n'; }, 1000);要截取1000这个值。经过分析,我发现setTimeout()这个函数闭合的圆括号)与前一个逗号,之间的内容,就是要截取的值。
想了想,要确定闭合括号)的位置,需要和开始位置(setTimeout之后)的括号( 匹配。看了些文档后,写了下面的方法:
function match(str, startStr, item) { var counter = 0, end = -1, matchLeft = item.charAt(0), matchRight = item.charAt(1), start = str.indexOf(startStr) + startStr.length; search(start + 1); function search(position) { end = str.indexOf(matchRight, position); if (end != -1) { counter++; var subStr = str.substring(start + 1, end).match(eval("/\\" + matchLeft + "/g")); if (subStr !== null) { var numsOfMatchLeft = subStr.length; } else if (subStr === null) { return; } if (counter > numsOfMatchLeft) { return; } else { arguments.callee(end + 1); } } else { console.warn('输入的配对符号有误'); } } return [start, end]; }match函数接收3个参数,str是要匹配的文本,startStr是需匹配字符,在文本中的具体位置,为了保证唯一性,一般要带入字符左侧若干文本,item是要匹配的符号,按左右顺序写全两个,如'()','{}'等。匹配最上面的setTimeout那个例子,可以这样调用。
var text = 'setTimeout(function() {\ output.innerText += \'第三个异步函数,延迟1秒执行\n\';\ }, 1000);' match(text,'setTimeout(','()'); //返回符号的开始,结束位置数组 //[11, 71]左右匹配,只要把中间所有的匹配项找到即可。
以 ()为例,首先从欲匹配符号(位置的右侧开始寻找),设定一个累加计数器,用来记录)的数量,如果找到,记下)的位置,计数器自增。
并且在(的位置与)的位置间,查找(的数量,与计数器进行比较。如果计数器的值小于(的数量,说明该)不是最终的与最开头的(相匹配的括号。如果计数器的值等于(的数量,说明所有()已经一一对应,下一个)就是最终的匹配括号。
重复上面的步骤,最终得到括号的位置。
这种方法不局限于括号,理论上可义匹配不相同的任意两项,也不局限于长度为1的字符,对位置稍加修改即可。
