Что является заменойВсе производительности секрет? [Вызов HTML]
Я потратил некоторое время на лучший способ избежать html-строки и нашел некоторые дискуссии по этому поводу: обсуждение 1 обсуждение 2. Это приводит меня к replaceAll. Затем я сделал тесты производительности и попытался найти решение, добившееся такой же скорости без успеха: (
Вот мой окончательный набор тестов. Я нашел его в сети и расширил свои попытки (4 случая внизу) и до сих пор не может достичь производительности replaceAll()
.
Что такое секретная ведьма делает решение replaceAll()
настолько быстрым?
Поздравил!
Фрагменты кода:
String.prototype.replaceAll = function(str1, str2, ignore)
{
return this.replace(new RegExp(str1.replace(/([\/\,\!\\\^\$\{\}\[\]\(\)\.\*\+\?\|\<\>\-\&])/g,"\\$&"),(ignore?"gi":"g")),(typeof(str2)=="string")?str2.replace(/\$/g,"$$$$"):str2);
};
кредиты для qwerty
Самый быстрый случай:
html.replaceAll('&', '&').replaceAll('"', '"').replaceAll("'", ''').replaceAll('<', '<').replaceAll('>', '>');
Ответы
Ответ 1
Наконец-то я нашел его!
Спасибо Jack за то, что указали мне на jsperf specific
Следует отметить, что результаты испытаний странные; когда .replaceAll() является определенный в Benchmark.prototype.setup, он работает в два раза быстрее по сравнению с тем, когда он определен глобально (т.е. внутри тега). Я все еще не уверен, почему это так, но это определенно должно быть связано с как работает jsperf.
Ответ:
replaceAll
- это значение предела/ошибки jsperf, вызванное специальной последовательностью "\\$&"
, поэтому результаты были неправильными.
compile()
- при вызове без аргумента он изменяет определение regexp на /(?:)
. Я не знаю, если это ошибка или что-то в этом роде, но результат производительности был дрянным после его вызова.
Вот мой результат безопасных тестов.
Наконец, я подготовил правильные тестовые примеры.
В результате, для HTML лучше всего использовать его для использования на основе собственного DOM-решения, например:
document.createElement('div').appendChild(document.createTextNode(html)).parentNode.innerHTML
или если вы повторяете это много раз, вы можете сделать это с помощью подготовленных переменных:
//prepare variables
var DOMtext = document.createTextNode("test");
var DOMnative = document.createElement("span");
DOMnative.appendChild(DOMtext);
//main work for each case
function HTMLescape(html){
DOMtext.nodeValue = html;
return DOMnative.innerHTML
}
Спасибо всем за сотрудничество и размещение комментариев и указаний.
описание ошибки jsperf
String.prototype.replaceAll
определяется следующим образом:
function (str1, str2, ignore) {
return this.replace(new RegExp(str1.replace(repAll, "\\#{setup}"), (ignore ? "gi" : "g")), (typeof(str2) == "string") ? str2.replace(/\$/g, "$$") : str2);
}
Ответ 2
Что касается производительности, я обнаружил, что функция ниже так же хороша, как и она:
String.prototype.htmlEscape = function() {
var amp_re = /&/g, sq_re = /'/g, quot_re = /"/g, lt_re = /</g, gt_re = />/g;
return function() {
return this
.replace(amp_re, '&')
.replace(sq_re, ''')
.replace(quot_re, '"')
.replace(lt_re, '<')
.replace(gt_re, '>');
}
}();
Он инициализирует регулярные выражения и возвращает замыкание, которое фактически выполняет замену.
Тест производительности
Следует отметить, что результаты испытаний странные; когда .replaceAll()
определяется внутри Benchmark.prototype.setup
, он работает в два раза быстрее, чем когда он определен глобально (т.е. внутри тега <script>
). Я все еще не уверен, почему это так, но это определенно должно быть связано с тем, как работает jsperf.
Использование RegExp.compile()
Я хотел избежать использования устаревшей функции, главным образом потому, что этот вид производительности должен выполняться автоматически современными браузерами. Здесь версия с скомпилированными выражениями:
String.prototype.htmlEscape2 = function() {
var amp_re = /&/g, sq_re = /'/g, quot_re = /"/g, lt_re = /</g, gt_re = />/g;
if (RegExp.prototype.compile) {
amp_re.compile();
sq_re.compile();
quot_re.compile();
lt_re.compile();
gt_re.compile();
}
return function() {
return this
.replace(amp_re, '&')
.replace(sq_re, ''')
.replace(quot_re, '"')
.replace(lt_re, '<')
.replace(gt_re, '>');
}
}
Делая это, удаляет все остальное из воды!
Тест производительности
Причина, по которой .compile()
дает такое повышение производительности, заключается в том, что когда вы компилируете глобальное выражение, например. /a/g
он преобразуется в /(?:)/
(в Chrome), что делает его бесполезным.
Если компиляция не может быть выполнена, браузер должен выкинуть ошибку, а не просто ее уничтожить.
Ответ 3
На самом деле есть более быстрые способы сделать это.
Если вы можете сделать встроенный сплит и присоединиться, вы получите лучшую производительность.
//example below
var test = "This is a test string";
var test2 = test.split("a").join("A");
Попробуйте это и запустите тест производительности.