显然,这比我想象的要难找。它甚至是如此简单……

JavaScript中是否内置了与PHP的htmlspecialchars相同的函数?我知道自己实现它相当容易,但如果可用的话,使用内置函数会更好。

对于那些不熟悉PHP的人,htmlspecialchars将<htmltag/>转换为&lt;htmltag/&gt;

我知道escape()和encodeURI()不是这样工作的。


当前回答

还有一种方法是完全放弃所有的字符映射,而是将所有不需要的字符转换为它们各自的数字字符引用,例如:

function escapeHtml(raw) {
    return raw.replace(/[&<>"']/g, function onReplace(match) {
        return '&#' + match.charCodeAt(0) + ';';
    });
}

注意,指定的RegEx只处理OP想要转义的特定字符,但是,根据转义HTML将要使用的上下文,这些字符可能是不够的。Ryan Grove的文章There's more to HTML转义than &, <, >, and”是关于这个主题的很好的阅读。根据您的上下文,为了避免XSS注入,很可能需要以下RegEx:

var regex = /[&<>"'` !@$%()=+{}[\]]/g

其他回答

function htmlspecialchars(str) {
 if (typeof(str) == "string") {
  str = str.replace(/&/g, "&amp;"); /* must do &amp; first */
  str = str.replace(/"/g, "&quot;");
  str = str.replace(/'/g, "&#039;");
  str = str.replace(/</g, "&lt;");
  str = str.replace(/>/g, "&gt;");
  }
 return str;
 }

对于Node.js用户(或在浏览器中使用Jade运行时的用户),可以使用Jade的转义函数。

require('jade').runtime.escape(...);

如果别人在维护它,你自己写它就没有任何意义了。:)

还有一种方法是完全放弃所有的字符映射,而是将所有不需要的字符转换为它们各自的数字字符引用,例如:

function escapeHtml(raw) {
    return raw.replace(/[&<>"']/g, function onReplace(match) {
        return '&#' + match.charCodeAt(0) + ';';
    });
}

注意,指定的RegEx只处理OP想要转义的特定字符,但是,根据转义HTML将要使用的上下文,这些字符可能是不够的。Ryan Grove的文章There's more to HTML转义than &, <, >, and”是关于这个主题的很好的阅读。根据您的上下文,为了避免XSS注入,很可能需要以下RegEx:

var regex = /[&<>"'` !@$%()=+{}[\]]/g

您的解决方案代码有一个问题——它只转义每个特殊字符的第一次出现。例如:

escapeHtml('Kip\'s <b>evil</b> "test" code\'s here');
Actual:   Kip&#039;s &lt;b&gt;evil</b> &quot;test" code's here
Expected: Kip&#039;s &lt;b&gt;evil&lt;/b&gt; &quot;test&quot; code&#039;s here

下面是正常工作的代码:

function escapeHtml(text) {
  return text
      .replace(/&/g, "&amp;")
      .replace(/</g, "&lt;")
      .replace(/>/g, "&gt;")
      .replace(/"/g, "&quot;")
      .replace(/'/g, "&#039;");
}

更新

下面的代码将产生与上面相同的结果,但它的性能更好,特别是在大块文本上(感谢jbo5112)。

function escapeHtml(text) {
  var map = {
    '&': '&amp;',
    '<': '&lt;',
    '>': '&gt;',
    '"': '&quot;',
    "'": '&#039;'
  };
  
  return text.replace(/[&<>"']/g, function(m) { return map[m]; });
}

使用jQuery可以像这样:

var escapedValue = $('<div/>').text(value).html();

用jQuery转义HTML字符串

正如注释中提到的,双引号和单引号在此实现中保持原样。这意味着如果您需要将元素属性作为原始html字符串,则不应使用此解决方案。