静的JavaScriptアナライザーと、学習に役立つエラー(パート1)

私のコードのすべての行が初めて完全に正しいわけではありません。 まあ、場合によっては...時々...わかりました-ほとんどありません。 真実は、自分の愚かな間違いを修正するのに、私が望むよりもはるかに多くの時間を費やしていることです。 それが、私が書くほとんどすべてのJavaScriptファイルで静的アナライザーを使用する理由です。



静的アナライザーは、コードをスキャンして、実行前にエラーを見つけます。 強制の構文(スペースではなくタブなど)のチェックなどの簡単なチェックと、機能が複雑すぎないかどうかのチェックなどのより一般的なチェックを実行します。 また、静的アナライザーは、テスト中に検出できないエラー(===ではなく==など)を探します。



大規模なプロジェクトや大規模なチームで作業している場合、実際には見かけほど単純ではないことが判明した「単純な」バグを見つけるのに少し助けられることはありません。





JSLint、JSHintおよびClosure Compiler



JavaScriptの静的パーサーには、JSLint、JSHint、およびClosure Compilerの3つの主なオプションがあります。



ジャスリント



JSLintは、JavaScript用の最初の静的パーサーです。 公式Webサイトで実行するか、ローカルファイルで実行できるアドオンのいずれかを使用できます。 JSLintは多くの重要なエラーを検出しますが、非常に困難です。 印象的な例は次のとおりです。



var s = 'mystring'; for (var i = 0; i < s.length; i++) { console.log(s.charAt(i)); }
      
      







JSLintは、このコードで2つのエラーを示します。



 Unexpected '++'. Move 'var' declarations to the top of the function.
      
      







最初の問題は、ループ内の変数iの定義です。 JSLintは、ループ定義の最後で++演算子も受け入れません。 彼はコードを次のようにしたいと考えています。



 var s = 'mystring'; var i; for (i = 0; i < s.length; i = i + 1) { console.log(s.charAt(i)); }
      
      







JSLintの作成者に感謝しますが、私にとってはバストです。 アントン・コワレフにとっては難しいことがわかったため、彼はJSHintを作成しました。



ジュシント



JSHintはJSLintと同じように機能しますが、Node.jsに加えて記述されているため、より柔軟です。 JSHintには多数のオプションが含まれており、独自のレポートジェネレーターを作成してカスタムチェックを実行できます。

サイトからJSHintを起動できますが、ほとんどの場合、Node.jsを使用してJSHintをローカルコマンドラインツールとしてインストールすることをお勧めします 。 JSHintをインストールすると、次のコマンドを使用してファイルで起動できます。



 jshint test.js
      
      







JSHintには一般的なテキストエディタ用のプラグインも含まれているため、コードを記述しながら実行できます。



クロージャコンパイラ



GoogleのClosure Compilerは、まったく異なる種類のプログラムです。 その名前が示すように、検証用のプログラムであるだけでなく、コンパイラでもあります。 Javaで書かれており、Mozilla Rhinoアナライザーに基づいています。 Closure Compilerには、基本的なコード検証を実行するためのシンプルモードと、追加の検証を実行して特定のタイプの定義が確実に適用されるようにするより複雑なモードが含まれています。



Closure CompilerはJavaScriptコードのバグを報告しますが、JavaScriptの最小化バージョンも作成します。 コンパイラは、空白、コメント、未使用の変数を削除し、長い式を単純化して、スクリプトを可能な限りコンパクトにします。



Googleは非常にシンプルなバージョンのコンパイラをオンラインで提供していますが 、おそらくClosure Compilerをダウンロードしてローカルで実行することをお勧めします



コードを確認した後、コンパイラを閉じて、ファイルを1つの最小化ファイルにリストします。 したがって、compiler.jarファイルをダウンロードして実行できます。



 java -jar compiler.jar --js_output_file compress.js --js test1.js --js test2.js
      
      







適切な検証ツールの選択



私のプロジェクトでは、Closure CompilerとJSHintを組み合わせています。 Closure Compilerは最小化と基本的な検証を実行し、JSHintはより複雑なコード分析を実行します。 これらの2つのプログラムは連携して機能し、それぞれが他のプログラムでは不可能な領域をカバーしています。 さらに、JSHint拡張機能を使用して、カスタム検証プログラムを作成できます。 私が書いた一般的なプログラムの1つは、プロジェクトに含めるべきではない関数の呼び出しなど、必要のない特定の関数をチェックします。



いくつかの検証プログラムを見てきたので、いくつかの悪いコードを見てみましょう。 これらの6つの例はそれぞれ、書く価値のないコードであり、コード検証プログラムがあなたを救うことができる状況です。



この記事のほとんどの例ではJSHintが使用されますが、通常、クロージャーコンパイラは同様の警告を出します。



==または===?



JavaScriptは動的型付け言語です。 書き込みプロセス中にタイプを決定する必要はなく、それらは起動時に存在します。



JavaScriptは、これらの動的タイプを制御する2つの比較演算子、==と===を提供します。 例を見てみましょう。



 var n = 123; var s = '123'; if (n == s) { alert(' '); } if (n === s) { alert(' '); }
      
      





比較演算子==は、JavaScriptが根付くC言語の名残です。 ほとんどの場合、その使用は間違いです。値を型とは別に比較することは、開発者が本当に望んでいることではありません。 実際、「百二十三」という数字は「一二三」という線とは異なります。 これらの文は綴りやすく、さらに読みやすくなっています。 このコードをJSHintで確認すると、次のものが得られます。



 test.js: line 9, col 12, Expected '===' and instead saw '=='.
      
      







未定義の変数と遅延定義



簡単なコードから始めましょう:



 function test() { var myVar = 'Hello, World'; console.log(myvar); }
      
      







バグを参照してください? 私は毎回この間違いを犯します。 このコードを実行すると、エラーが発生します。



 ReferenceError: myvar is not defined
      
      







問題をもう少し複雑にしてみましょう:



 function test() { myVar = 'Hello, World'; console.log(myVar); }
      
      







このコードを実行すると、次のものが得られます。



 Hello, World
      
      





この2番目の例は機能しますが、非常に予期しない副作用がいくつかあります。 JavaScriptの変数とスコープを定義するためのルールは、せいぜい混乱させるだけです。 最初のケースでは、JSHintは次を報告します。



 test.js: line 3, col 17, 'myvar' is not defined.
      
      







2番目のケースでは、彼はこれを報告します。



 test.js: line 2, col 5, 'myVar' is not defined. test.js: line 3, col 17, 'myVar' is not defined.
      
      







最初の例は、実行時エラーを回避するのに役立ちます。 アプリケーションをテストする必要はありません-JSHintはエラーを見つけます。 2番目の例は、テストの結果としてバグを見つけられないため、さらに悪い例です。



2番目の例の問題は、知らないうちに見えず複雑です。 変数myVarはスコープから消え、グローバルスコープに上昇しました。 これは、テスト関数を実行した後でも、Hello、Worldという値が存在することを意味します。 これは「グローバルな可視性汚染」と呼ばれます。



変数myVarは、テスト関数の後に実行される他のすべての関数に対して存在します。 テスト関数を実行した後、次のコードを実行します。



 console.log('myVar: ' + myVar);
      
      







あなたはまだHello、Worldを取得しています。 myVar変数は、リリース前に一晩中見ている複雑なバグにつながるパターンとしてコード全体にハングアップします。これはすべて、varの入力を忘れたためです。



Habré読者向けの便利なPaystoソリューション:
今すぐクレジットカードで支払いを受けましょう。 サイト、IPおよびLLCなし。

オンライン企業からの支払いを受け入れます。 サイト、IPおよびLLCなし。

サイトの会社からの支払いを受け入れます。 ドキュメント管理とオリジナルの交換。

法人との販売およびサービス取引の自動化。 計算の仲介なし。






All Articles