2013-07-03 6 views
10

私はhtml文字列をエスケープするために最善の方法を探していましたが、そのことに関するいくつかの議論が見つかりました:discussion 1discussion 2。それは私にreplaceAllの機能につながる。パフォーマンステストを行い、同様の速度を達成して解決策を見つけようとしました。(replaceAllのパフォーマンスシークレットとは何ですか? [HTMLエスケープ]

ここでは最終的にtest case setです。ネットで見つけて試してみましょう(下部に4つのケースがあります)。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); 
}; 
:秘密の魔女が replaceAll()ソリューションとてもスピーディー

挨拶

コードスニペットを作成されたどのようなパフォーマンス

これまでqwerty

最速の場合の

クレジット:

html.replaceAll('&', '&amp;').replaceAll('"', '&quot;').replaceAll("'", '&#39;').replaceAll('<', '&lt;').replaceAll('>', '&gt;'); 
+1

方法で構築された多くは、ネイティブコードで実装され、事前に最適化されている(正規表現が一つである)、それらをエミュレートJavascriptの方が早いのは簡単ではありません。 –

+0

確かに、なぜ "新しいRegExpを置き換える"ケースが遅いのですか? RegExpも使用します。 – Saram

+0

はまだ正規表現なしで置き換えられるようですhttp://jsperf.com/replaceallvssplitjoin –

答えて

4

最後に私はそれを見つけました!特定jsperfに私を指しているため おかげJack

私はテスト結果が奇妙であることに注意すべきです。 .replaceAll()がBenchmark.prototype.setup内で定義された の場合、グローバルに定義されたとき(つまりタグ内)に比べて2倍高速の が実行されます。 私はまだその理由は分かりませんが、確かにjsperf自体がどのように動作するのかは、 に関係している必要があります。

答えは次のとおりです。

replaceAll - 結果が間違っていたので、これは、特別なシーケンス"\\$&"によって引き起こさjsperf制限/バグに達します。

compile() - 引数を指定しないで呼び出されると、regexpの定義が/(?:)に変更されます。私はそれがバグか何かであるかどうかは分かりませんが、それが呼び出された後のパフォーマンス結果は馬鹿げていました。

ここは私のresult safe testsです。

最後に、proper test casesを用意しました。

結果は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); 
} 
+1

jsperfのバグにリンクできますか? –

+0

@Jackバグテスト(setup()手続きでreplaceAllが定義されている)を起動すると、コンソールに行き、 'String.prototype.replaceAll'の本文を表示します。私は1分以内に何かコメントして答えます。 – Saram

-1

は、実際にこれを行うには、より高速な方法があります。

インライン分割と結合ができれば、より良いパフォーマンスが得られます。

//example below 
var test = "This is a test string"; 
var test2 = test.split("a").join("A"); 

これを試して、パフォーマンステストを実行してください。限りのパフォーマンスが行くよう

+3

は確認できません: http://jsperf.com/htmlencoderegex/31 – Saram

+0

これを確認してくださいhttp://dynamic-tools.net/toolbox/replaceAll/ – blganesh101

+0

replaceAll関数を使用する:** 0.054 ** seconds/ ** 0.106 **秒/ インライン分割/結合:** 0.111 **秒/ インラインRegExpオブジェクト:** 0.182 **秒 文字列のないインラインRegExpオブジェクト:** 0.134 **秒 – Saram

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, '&amp;') 
      .replace(sq_re, '&#39;') 
      .replace(quot_re, '&quot;') 
      .replace(lt_re, '&lt;') 
      .replace(gt_re, '&gt;'); 
    } 
}(); 

それは正規表現を初期化し、実際の交換を行い、クロージャを返します。

Performance test

私は、テスト結果が奇妙であることに注意すべきです。 .replaceAll()が定義されている場合Benchmark.prototype.setupグローバルに定義されている場合(すなわち<script>タグ内)と比較して2倍高速です。私はまだそれがなぜなのかまだ分かりませんが、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, '&amp;') 
      .replace(sq_re, '&#39;') 
      .replace(quot_re, '&quot;') 
      .replace(lt_re, '&lt;') 
      .replace(gt_re, '&gt;'); 
    } 
} 

これですべてが水から吹き飛ばされます。

Performance test

.compile()は、このようなパフォーマンスの向上を与える理由はあるので、あなたがグローバルな表現をコンパイルする場合、例えば/a/g(Chromeの場合)/(?:)/に変換され、使用できなくなります。

コンパイルができない場合、ブラウザはエラーをスローするのではなく、エラーをスローする必要があります。

+0

@ Joachim Isakssonのコメント。私は彼がトリックを見つけたと思う。 – Saram

+0

@Saram私は非推奨の '.compile()'でテストしませんでしたが、それが有用な統計になるのではないかと疑います。テストベンチマークの何かが結果に影響を与えています。 –

+0

@Saramまた、[MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp)によると、リテラル正規表現*は*コンパイルされます。 –