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

cal*_*lum 93 html javascript regex string performance

我正在写一个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;') ;
}
Run Code Online (Sandbox Code Playgroud)

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

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

(我有一个想法是不打扰编码大于号 - 这会有任何真正的危险吗?)

Web*_*ner 92

这是你可以这样做的一种方法:

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

function unescapeHTML(html) {
    escape.innerHTML = html;
    return escape.textContent;
}
Run Code Online (Sandbox Code Playgroud)

这是一个演示.

  • 不确定如何/什么/为什么 - 但这是天才. (11认同)
  • @jazkat我没有使用那个功能.我使用的转义变量,我在示例中定义了自己. (3认同)
  • 看起来它正在利用TextArea元素的现有代码来转义文本文本.非常好,我认为这个小技巧将会找到另一个家. (2认同)
  • 但这是否会丢失空白等。 (2认同)

Mar*_*ijn 75

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

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

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

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

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

你的方式似乎更快......

但是你为什么需要呢?

  • @ user142019:这仍然是正确的做法. (8认同)
  • 实际上,如果将转义值放在html元素的属性中,则需要转义>符号.否则它会破坏该html元素的标记. (4认同)
  • @callum:不.我对列举我认为"可能出现问题"的案件不感兴趣(尤其是因为这是意外/遗忘的情况会伤害到你,当你最不想要的时候).我对标准编码感兴趣(所以意外/遗忘的情况不会伤害你_by definition_).我不能强调这是多么重要.`>`是HTML中的一个特殊字符,所以逃避它.就那么简单.:) (3认同)
  • @LightnessRacesinOrbit它是相关的,因为问题是什么是最快的方法.如果可以跳过`>`替换,那会使它更快. (3认同)
  • 没有必要逃避`>`. (2认同)
  • 在普通文本中,转义字符很少见。如果您关心最大速度,最好仅在需要时调用替换:`if (/[&lt;&gt;&amp;"]/.test(str) { ... }` (2认同)

Ara*_*yan 27

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;"
Run Code Online (Sandbox Code Playgroud)

  • 像这样添加到`String`它应该是**escapeHtml**,因为它不是一般的String转义.那就是`String.escapeHtml`是正确的,但是`String.escape`引发了一个问题,"逃避什么?" (10认同)
  • 是的好主意.这几天我已经放弃了扩展原型以避免冲突. (3认同)

Kev*_*son 10

AngularJS源代码还有一个angular-sanitize.js内的版本.

var SURROGATE_PAIR_REGEXP = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g,
    // Match everything outside of normal chars and " (quote character)
    NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g;
/**
 * Escapes all potentially dangerous characters, so that the
 * resulting string can be safely inserted into attribute or
 * element text.
 * @param value
 * @returns {string} escaped text
 */
function encodeEntities(value) {
  return value.
    replace(/&/g, '&amp;').
    replace(SURROGATE_PAIR_REGEXP, function(value) {
      var hi = value.charCodeAt(0);
      var low = value.charCodeAt(1);
      return '&#' + (((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000) + ';';
    }).
    replace(NON_ALPHANUMERIC_REGEXP, function(value) {
      return '&#' + value.charCodeAt(0) + ';';
    }).
    replace(/</g, '&lt;').
    replace(/>/g, '&gt;');
}
Run Code Online (Sandbox Code Playgroud)


Jul*_*egg 9

最快的方法是:

function escapeHTML(html) {
    return document.createElement('div').appendChild(document.createTextNode(html)).parentNode.innerHTML;
}
Run Code Online (Sandbox Code Playgroud)

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

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


bap*_*ptx 8

一体化脚本:

// HTML entities Encode/Decode

function htmlspecialchars(str) {
    var map = {
        "&": "&amp;",
        "<": "&lt;",
        ">": "&gt;",
        "\"": "&quot;",
        "'": "&#39;" // ' -> &apos; for XML only
    };
    return str.replace(/[&<>"']/g, function(m) { return map[m]; });
}
function htmlspecialchars_decode(str) {
    var map = {
        "&amp;": "&",
        "&lt;": "<",
        "&gt;": ">",
        "&quot;": "\"",
        "&#39;": "'"
    };
    return str.replace(/(&amp;|&lt;|&gt;|&quot;|&#39;)/g, function(m) { return map[m]; });
}
function htmlentities(str) {
    var textarea = document.createElement("textarea");
    textarea.innerHTML = str;
    return textarea.innerHTML;
}
function htmlentities_decode(str) {
    var textarea = document.createElement("textarea");
    textarea.innerHTML = str;
    return textarea.value;
}
Run Code Online (Sandbox Code Playgroud)

http://pastebin.com/JGCVs0Ts


小智 5

更快或更短的解决方案是:

escaped = new Option(html).innerHTML
Run Code Online (Sandbox Code Playgroud)

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

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

  • 简洁的单行代码,但在正则表达式之后是[最慢的方法](https://jsperf.com/htmlentityencode/1)。另外,根据[规范](https://www.w3.org/TR/2012/WD-html5-20121025/the-option-element.html#dom-option),此处的文本可以删除空格 (5认同)