[英]How can I improve the performance of my JavaScript text formatter?
I am allowing my users to wrap words with "*", "/", "_", and "-" as a shorthand way to indicate they'd like to bold, italicize, underline, or strikethrough their text. 我允许我的用户用“ *”,“ /”,“ _”和“-”换行,以表示他们想要加粗,斜体,下划线或删除线。 Unfortunately, when the page is filled with text using this markup, I'm seeing a noticeable (borderline acceptable) slow down.
不幸的是,当页面使用此标记填充文本时,我看到了明显的(可接受的边界线)减速。
Here's the JavaScript I wrote to handle this task. 这是我编写的用于处理此任务的JavaScript。 Can you please provide feedback on how I could speed things up?
您能否提供有关如何加快速度的反馈?
function handleContentFormatting(content) {
content = handleLineBreaks(content);
var bold_object = {'regex': /\*(.|\n)+?\*/i, 'open': '<b>', 'close': '</b>'};
var italic_object = {'regex': /\/(?!\D>|>)(.|\n)+?\//i, 'open': '<i>', 'close': '</i>'};
var underline_object = {'regex': /\_(.|\n)+?\_/i, 'open': '<u>', 'close': '</u>'};
var strikethrough_object = {'regex': /\-(.|\n)+?\-/i, 'open': '<del>', 'close': '</del>'};
var format_objects = [bold_object, italic_object, underline_object, strikethrough_object];
for( obj in format_objects ) {
content = handleTextFormatIndicators(content, format_objects[obj]);
}
return content;
}
//@param obj --- an object with 3 properties:
// 1.) the regex to search with
// 2.) the opening HTML tag that will replace the opening format indicator
// 3.) the closing HTML tag that will replace the closing format indicator
function handleTextFormatIndicators(content, obj) {
while(content.search(obj.regex) > -1) {
var matches = content.match(obj.regex);
if( matches && matches.length > 0) {
var new_segment = obj.open + matches[0].slice(1,matches[0].length-1) + obj.close;
content = content.replace(matches[0],new_segment);
}
}
return content;
}
Your code is forcing the browser to do a whole lot of repeated, wasted work. 您的代码迫使浏览器执行大量重复的,浪费的工作。 The approach you should be taking is this:
您应该采用的方法是:
As to how to combine the regular expressions, well, it's not very pretty in JavaScript but it looks like this. 关于如何组合正则表达式,在JavaScript中它不是很漂亮,但是看起来像这样。 First, you need a regex for a string of zero or more "uninteresting" characters.
首先,您需要一个用于零个或多个“无趣”字符的字符串的正则表达式。 That should be the first capturing group in the regex.
那应该是正则表达式中的第一个捕获组。 Next should be the alternates for the target strings you're looking for.
接下来应该是您要查找的目标字符串的替代项。 Thus the general form is:
因此,一般形式为:
var tokenizer = /(uninteresting pattern)?(?:(target 1)|(target 2)|(target 3)| ... )?/;
When you match that against the source string, you'll get back a result array that will contain the following: 将其与源字符串匹配时,您将返回一个包含以下内容的结果数组:
result[0] - entire chunk of string (not used)
result[1] - run of uninteresting characters
result[2] - either an instance of target type 1, or null
result[3] - either an instance of target type 2, or null
...
Thus you'll know which kind of replacement target you saw by checking which of the target regexes are non empty. 因此,通过检查哪些目标正则表达式为非空,您将知道所看到的替换目标类型。 (Note that in your case the targets can conceivably overlap; if you intend for that to work, then you'll have to approach this as a full-blown parsing problem I suspect.)
(请注意,在您的情况下,目标可能会重叠;如果您打算使目标起作用,那么您将不得不将其视为一个成熟的解析问题,我怀疑。)
Change your regex with the flags /ig
and remove the while loop. 使用
/ig
标志更改您的正则表达式,并删除while循环。
Change your for(obj in format_objects)
loop with a normal for loop, because format_objects
is an array. 用常规的for循环更改
for(obj in format_objects)
循环,因为format_objects
是一个数组。
Okay, I took the time to write an even faster and simplified solution, based on your code: 好的,我花了一些时间根据您的代码编写一个更快,更简化的解决方案:
function handleContentFormatting(content) {
content = handleLineBreaks(content);
var bold_object = {'regex': /\*([^*]+)\*/ig, 'replace': '<b>$1</b>'},
italic_object = {'regex': /\/(?!\D>|>)([^\/]+)\//ig, 'replace': '<i>$1</i>'},
underline_object = {'regex': /\_([^_]+)\_/ig, 'replace': '<u>$1</u>'},
strikethrough_object = {'regex': /\-([^-]+)\-/ig, 'replace': '<del>$1</del>'};
var format_objects = [bold_object, italic_object, underline_object, strikethrough_object],
i = 0, foObjSize = format_objects.length;
for( i; i < foObjSize; i++ ) {
content = handleTextFormatIndicators(content, format_objects[i]);
}
return content;
}
//@param obj --- an object with 2 properties:
// 1.) the regex to search with
// 2.) the replace string
function handleTextFormatIndicators(content, obj) {
return content.replace(obj.regex, obj.replace);
}
Here is a demo . 这是一个演示 。
This will work with nested and/or not nested formatting boundaries. 这将适用于嵌套和/或非嵌套格式边界。 You can omit the function
handleTextFormatIndicators
altogether if you want to, and do the replacements inline inside handleContentFormatting
. 如果需要,可以完全省略功能
handleTextFormatIndicators
,并在handleContentFormatting
内联替换。
You can do things like: 你可以这样做:
function formatText(text){
return text.replace(
/\*([^*]*)\*|\/([^\/]*)\/|_([^_]*)_|-([^-]*)-/gi,
function(m, tb, ti, tu, ts){
if(typeof(tb) != 'undefined')
return '<b>' + formatText(tb) + '</b>';
if(typeof(ti) != 'undefined')
return '<i>' + formatText(ti) + '</i>';
if(typeof(tu) != 'undefined')
return '<u>' + formatText(tu) + '</u>';
if(typeof(ts) != 'undefined')
return '<del>' + formatText(ts) + '</del>';
return 'ERR('+m+')';
}
);
}
This will work fine on nested tags, but will not with overlapping tags, which are invalid anyway. 这在嵌套标签上可以正常使用,但对于重叠标签则无效,但重叠标签仍然无效。
Example at http://jsfiddle.net/m5Rju/ http://jsfiddle.net/m5Rju/上的示例
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.