[英]Fastest method to escape HTML tags as HTML entities?
我正在編寫一個 Chrome 擴展程序,它涉及執行以下許多工作:通過將<
、 >
和&
轉換為<
來清理可能包含 HTML 標簽的字符串<
, >
和&
, 分別。
(換句話說,與 PHP 的htmlspecialchars(str, ENT_NOQUOTES)
——我認為沒有任何真正需要轉換雙引號字符。)
這是迄今為止我發現的最快的功能:
function safe_tags(str) {
return str.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>') ;
}
但是當我必須一次運行幾千個字符串時,仍然有很大的滯后。
任何人都可以改進嗎? 它主要用於 10 到 150 個字符之間的字符串,如果這有所不同的話。
(我的一個想法是不要對大於號進行編碼——這樣做會有什么真正的危險嗎?)
這是您可以執行此操作的一種方法:
var escape = document.createElement('textarea');
function escapeHTML(html) {
escape.textContent = html;
return escape.innerHTML;
}
function unescapeHTML(html) {
escape.innerHTML = html;
return escape.textContent;
}
您可以嘗試傳遞一個回調函數來執行替換:
var tagsToReplace = {
'&': '&',
'<': '<',
'>': '>'
};
function replaceTag(tag) {
return tagsToReplace[tag] || tag;
}
function safe_tags_replace(str) {
return str.replace(/[&<>]/g, replaceTag);
}
這里是一個性能測試: http : //jsperf.com/encode-html-entities與重復調用replace
函數進行比較,並使用Dmitrij提出的DOM方法。
你的方式似乎更快...
不過,你為什么需要它?
Martijn 的方法作為原型函數:
String.prototype.escape = function() {
var tagsToReplace = {
'&': '&',
'<': '<',
'>': '>'
};
return this.replace(/[&<>]/g, function(tag) {
return tagsToReplace[tag] || tag;
});
};
var a = "<abc>";
var b = a.escape(); // "<abc>"
最快的方法是:
function escapeHTML(html) {
return document.createElement('div').appendChild(document.createTextNode(html)).parentNode.innerHTML;
}
這種方法比基於“replace”的方法快兩倍,參見http://jsperf.com/htmlencoderegex/35 。
一個更快/更短的解決方案是:
escaped = new Option(html).innerHTML
這與 JavaScript 的一些奇怪的痕跡有關,其中 Option 元素保留了一個自動執行此類轉義的構造函數。
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, '&').
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, '<').
replace(/>/g, '>');
}
多合一腳本:
// HTML entities Encode/Decode
function htmlspecialchars(str) {
var map = {
"&": "&",
"<": "<",
">": ">",
"\"": """,
"'": "'" // ' -> ' for XML only
};
return str.replace(/[&<>"']/g, function(m) { return map[m]; });
}
function htmlspecialchars_decode(str) {
var map = {
"&": "&",
"<": "<",
">": ">",
""": "\"",
"'": "'"
};
return str.replace(/(&|<|>|"|')/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;
}
function encode(r) { return r.replace(/[\\x26\\x0A\\x3c\\x3e\\x22\\x27]/g, function(r) { return "&#" + r.charCodeAt(0) + ";"; }); } test.value=encode('How to encode\\nonly html tags &<>\\'" nice & fast!'); /* \\x26 is &ersand (it has to be first), \\x0A is newline, \\x22 is ", \\x27 is ', \\x3c is <, \\x3e is > */
<textarea id=test rows=11 cols=55>www.WHAK.com</textarea>
Martijn 的方法作為單個函數處理“標記(在 javascript 中使用):
function escapeHTML(html) {
var fn=function(tag) {
var charsToReplace = {
'&': '&',
'<': '<',
'>': '>',
'"': '"'
};
return charsToReplace[tag] || tag;
}
return html.replace(/[&<>"]/g, fn);
}
我不完全確定速度,但如果您正在尋找簡單性,我建議使用 lodash/underscore轉義函數。
我會將XMLSerializer
添加到該堆中。 它在不使用任何對象緩存的情況下提供最快的結果(不在序列化程序上,也不在 Text 節點上)。
function serializeTextNode(text) {
return new XMLSerializer().serializeToString(document.createTextNode(text));
}
額外的好處是它支持與文本節點不同的序列化屬性:
function serializeAttributeValue(value) {
const attr = document.createAttribute('a');
attr.value = value;
return new XMLSerializer().serializeToString(attr);
}
您可以通過檢查規范來查看它實際替換的內容,包括 文本節點和屬性值。 完整的文檔有更多的節點類型,但概念是一樣的。
至於性能,它在不緩存時是最快的。 當您允許緩存時,在帶有子 Text 節點的 HTMLElement 上調用innerHTML
是最快的。 正則表達式將是最慢的(正如其他評論所證明的那樣)。 當然,XMLSerializer 在其他瀏覽器上可能更快,但在我(有限的)測試中, innerHTML
是最快的。
最快單線:
new XMLSerializer().serializeToString(document.createTextNode(text));
最快的緩存:
const cachedElementParent = document.createElement('div');
const cachedChildTextNode = document.createTextNode('');
cachedElementParent.appendChild(cachedChildTextNode);
function serializeTextNode(text) {
cachedChildTextNode.nodeValue = text;
return cachedElementParent.innerHTML;
}
節目有點晚了,但是使用encodeURIComponent()和decodeURIComponent() 有什么問題?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.