将 HTML 标签转义为 HTML 实体的最快方法?

IT技术 javascript html regex performance string
2021-02-08 12:08:18

我正在写一个Chrome扩展程序,包括做了很多以后的工作中:消毒的字符串可能包含HTML标签,通过转换<>&&lt;&gt;&amp;分别。

(换句话说,与 PHP 相同htmlspecialchars(str, ENT_NOQUOTES)——我认为没有任何真正需要转换双引号字符。)

这是迄今为止我发现的最快的函数:

function safe_tags(str) {
    return str.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;') ;
}

但是当我必须一次运行几千个字符串时,仍然有很大的滞后。

任何人都可以改进吗?它主要用于 10 到 150 个字符之间的字符串,如果这有区别的话。

(我的一个想法是不要对大于号进行编码——这样做会有什么真正的危险吗?)

6个回答

这是您可以执行此操作的一种方法:

var escape = document.createElement('textarea');
function escapeHTML(html) {
    escape.textContent = html;
    return escape.innerHTML;
}

function unescapeHTML(html) {
    escape.innerHTML = html;
    return escape.textContent;
}

这是一个演示。

不知道如何/什么/为什么 - 但这是天才。
2021-03-14 12:08:18
重新设计了演示。这是一个全屏版本:jsfiddle.net/Daniel_Hug/qPUEX/show/light
2021-03-19 12:08:18
但这是否会丢失空白等。
2021-03-19 12:08:18
@jazkat 我没有使用该功能。我使用的转义变量,我在示例中定义了自己。
2021-03-24 12:08:18
看起来它正在利用 TextArea 元素的现有代码来转义文字文本。非常好,我想这个小技巧是要找到另一个家。
2021-03-29 12:08:18

您可以尝试传递一个回调函数来执行替换:

var tagsToReplace = {
    '&': '&amp;',
    '<': '&lt;',
    '>': '&gt;'
};

function replaceTag(tag) {
    return tagsToReplace[tag] || tag;
}

function safe_tags_replace(str) {
    return str.replace(/[&<>]/g, replaceTag);
}

这里是一个性能测试:http : //jsperf.com/encode-html-entitiesreplace重复调用函数进行比较,并使用 Dmitrij 提出的 DOM 方法。

你的方式好像更快...

不过,你为什么需要它?

在普通文本中,转义字符很少见。如果您关心最大速度,最好仅在需要时调用替换:if (/[<>&"]/.test(str) { ... }
2021-03-21 12:08:18
实际上,如果将转义值放在 html 元素的属性中,则需要对 > 符号进行转义。否则它会破坏该 html 元素的标签。
2021-03-29 12:08:18
没有必要逃跑>
2021-04-05 12:08:18
@LightnessRacesinOrbit 这很重要,因为问题是什么是最快的方法。如果可以跳过>替换,那将使它更快。
2021-04-06 12:08:18
@callum:不。我对列举我认为“可能会出错”的案例不感兴趣(尤其是因为意外/被遗忘的案例会伤害你,并且在你最不期望的时候)。我对按照标准编码很感兴趣(所以根据定义,意外/被遗忘的情况不会伤害你)。我不能强调这是多么重要。>是 HTML 中的特殊字符,因此将其转义。就那么简单。:)
2021-04-09 12:08:18

Martijn 的方法作为原型函数:

String.prototype.escape = function() {
    var tagsToReplace = {
        '&': '&amp;',
        '<': '&lt;',
        '>': '&gt;'
    };
    return this.replace(/[&<>]/g, function(tag) {
        return tagsToReplace[tag] || tag;
    });
};

var a = "<abc>";
var b = a.escape(); // "&lt;abc&gt;"
String像这样添加它应该是escapeHtml,因为它通常不是对字符串的转义。这是String.escapeHtml正确的,但String.escape提出了一个问题,“逃避什么?”
2021-03-15 12:08:18
是的好主意。这些天我已经不再扩展原型以避免冲突。
2021-03-26 12:08:18
为示例加一。
2021-03-27 12:08:18
如果您的浏览器支持 Symbol,您可以使用它来避免污染 string-key 命名空间。var escape = new Symbol("escape"); String.prototype[escape] = function(){ ... }; “文本”[转义]();
2021-04-09 12:08:18

一个更快/更短的解决方案是:

escaped = new Option(html).innerHTML

这与 JavaScript 的一些奇怪的痕迹有关,其中 Option 元素保留了一个自动执行这种转义的构造函数。

归功于https://github.com/jasonmoo/t.js/blob/master/t.js

整洁的单行但正则表达式之后最慢的方法此外,根据规范,此处的文本可以去除空格
2021-03-27 12:08:18
请注意,@ShortFuse 的“最慢方法”链接使我的系统内存不足(大约 6GB 可用)并且 firefox 似乎在内存不足之前停止分配,因此不是杀死有问题的进程,linux 将坐在那里让你做硬断电。
2021-04-10 12:08:18

最快的方法是:

function escapeHTML(html) {
    return document.createElement('div').appendChild(document.createTextNode(html)).parentNode.innerHTML;
}

这种方法比基于“replace”的方法快两倍,参见http://jsperf.com/htmlencoderegex/35

来源:https : //stackoverflow.com/a/17546215/698168