在写一个随机生成密码的过程中,引用到了Mock.js这个库,测试过程发现了string方法测试的数据一多就会出现bug,这里把执行的@string(8,9)这个随机的方法也显示到随机的结果里面,如下:
后来查看源码发现是由于正则表达式替换的时候,$符号的特殊含义导致的,出现bug的方法代码为:
string: function(options) {
var result = '',
i, placeholders, ph, phed;
if (options.template.length) {
// 'foo': '★',
/* jshint -W041 */
if (options.rule.count == undefined) {
result += options.template
}
// 'star|1-5': '★',
for (i = 0; i < options.rule.count; i++) {
result += options.template
}
// 'email|1-10': '@EMAIL, ',
placeholders = result.match(Constant.RE_PLACEHOLDER) || [] // A-Z_0-9 > \w_
for (i = 0; i < placeholders.length; i++) {
ph = placeholders[i]
// 遇到转义斜杠,不需要解析占位符
if (/^\\/.test(ph)) {
placeholders.splice(i--, 1)
continue
}
phed = Handler.placeholder(ph, options.context.currentContext, options.context.templateCurrentContext, options)
// 只有一个占位符,并且没有其他字符
if (placeholders.length === 1 && ph === result && typeof phed !== typeof result) { //
result = phed
break
if (Util.isNumeric(phed)) {
result = parseFloat(phed, 10)
break
}
if (/^(true|false)$/.test(phed)) {
result = phed === 'true' ? true :
phed === 'false' ? false :
phed // 已经是布尔值
break
}
}
result = result.replace(ph, phed);
}
} else {
// 'ASCII|1-10': '',
// 'ASCII': '',
result = options.rule.range ? Random.string(options.rule.count) : options.template
}
return result;
}
主要是下面这一句导致的
result = result.replace(ph, phed);
原因是$符号有以下特殊含义,当生成的字符串包含如下组合的字符串,就会出现问题:
整改后的代码如下:
string: function(options) {
var result = '',
i, placeholders, ph, phed;
if (options.template.length) {
// 'foo': '★',
/* jshint -W041 */
if (options.rule.count == undefined) {
result += options.template
}
// 'star|1-5': '★',
for (i = 0; i < options.rule.count; i++) {
result += options.template
}
// 'email|1-10': '@EMAIL, ',
placeholders = result.match(Constant.RE_PLACEHOLDER) || [] // A-Z_0-9 > \w_
for (i = 0; i < placeholders.length; i++) {
ph = placeholders[i]
// 遇到转义斜杠,不需要解析占位符
if (/^\\/.test(ph)) {
placeholders.splice(i--, 1)
continue
}
phed = Handler.placeholder(ph, options.context.currentContext, options.context.templateCurrentContext, options)
if(phed.indexOf('$')>-1){
phed=phed.replace(/\$/g,'$ ');
}
// 只有一个占位符,并且没有其他字符
if (placeholders.length === 1 && ph === result && typeof phed !== typeof result) { //
result = phed
break
if (Util.isNumeric(phed)) {
result = parseFloat(phed, 10)
break
}
if (/^(true|false)$/.test(phed)) {
result = phed === 'true' ? true :
phed === 'false' ? false :
phed // 已经是布尔值
break
}
}
result = result.replace(ph, phed);
}
} else {
// 'ASCII|1-10': '',
// 'ASCII': '',
result = options.rule.range ? Random.string(options.rule.count) : options.template
}
return result.indexOf(' ')>-1?result.replace(/ /g,''):result;
}
主要是改了这两个地方:
if(phed.indexOf('$')>-1){
phed=phed.replace(/\$/g,'$ ');
}
和
return result.indexOf(' ')>-1?result.replace(/ /g,''):result;
思路如下:
- 替换前把$符号的组合拆掉,我是填充了个空格来处理;
- 替换完后,再把空格处理掉就行了