コンピューター ウィンドウズ インターネット

JavaScriptのセキュリティまたは安全なJSコードの書き方。 バージョン管理ツール

ALEXANDER MAYOROV、プログラマー、プログラミングの11年の経験、そのうちの7つはモバイルデバイスの開発に専念しました

JavaScriptでの静的型分析
Facebook FlowAnalyzerを試す

Facebookは、新しいオープンソースプロジェクトFlow(JavaScript用の静的コードアナライザー)を導入しました。 アナライザー開発の主な目的は、エラーの検索を簡素化することです。

さらに、Flowは、型を明示的に指定するためのTypeScriptスタイルのJavaScript構文拡張機能を提供します。 ECMAScript6仕様で導入された新機能の多くがサポートされています。

プログラミング言語での入力のトピックは、しばしば触れられます。 これはホリバーの主題であり、特定の言語のポジティブまたはネガティブな特性を決定します。 最近、JavaScriptでの入力について多くの話があります。 誰かがそれをそのまま好きです。 他のプログラミング言語に精通している人々、特に強力な明示的タイピングを使用している人々は、このアプローチを「サルの手榴弾」と考えています。 JavaScriptは大まかに動的に型付けされた言語であることは誰もが知っています。 フロントエンド開発の達人は、これを有利に使用する方法を学びましたが、コードが重すぎて理解できない場合があります。 JavaScriptプログラミングの世界に来たばかりの人は、インタプリタが行う魔法に戸惑い、突然エラーをキャッチすることがよくあります。 しかし、最初に、一般的なタイピングについて少し掘り下げてみましょう。 どんな感じ?

プログラミング言語での入力

タイピングによって、プログラミング言語は2つの大きなキャンプに分けられます-タイプされたものとタイプされていないものです。 たとえば、型付き言語には、C、Python、PHP、Lua、JavaScriptなどの言語が含まれます。 タイプされていない言語の例:アセンブラー、Forth、Brainfuck。 はいはい正確に。 JavaScriptは、他の多くのインタプリタ言語と同様に、型指定されています。 したがって、タイプされていないとは決して言えません。 特に就職の面接で。

次に、入力された言語はいくつかの重複するカテゴリに分類されます:

  • 静的または動的に型指定されます。
  • 強いまたは緩く型付けされている。
  • 明示的または暗黙的に入力されます。

静的に型付けされた言語

静的型付けでは、変数と関数の最終的な型はコンパイル時に設定されます。 コンパイラは、プログラムが起動する前であっても、型の不一致エラーを修正します。 言語の例:C、Java、C#。

動的に型付けされた言語

動的型付けでは、すべての型が実行時に検出されます。 そして、あなたが間違えた場合、あなたはあなたがプログラムを実行するときだけそれについて知るでしょう。 したがって、動的に入力するときは、エラーのチェックとキャッチに特別な注意を払うことが非常に重要です。 言語の例:JavaScript、PHP、Python、Ruby。

強い型付け(強い)

強く型付けされた言語は、式に異なる型を混在させることを許可せず、自動暗黙変換を実行しません。 たとえば、文字列から数値や文字列以外のタイプを減算することはできません。 言語の例:Java、Python、Haskell、Lisp。

緩いタイピング(弱い)

緩く型付けされた言語は、多くの暗黙的な変換を自動的に実行します。 あいまいに、精度や変換が失われる可能性がある場合でも、これを行います。 言語の例:PHP、JavaScript、VisualBasic。

明示的な入力

明示的に型指定された言語では、新しい変数/関数および引数の型を明示的に指定する必要があります。 言語の例:C ++、D、C#。

暗黙のタイピング

暗黙のタイピングを使用する言語では、タイプを指定するタスクはコンパイラー/インタープリターに転送されます。 言語の例:JavaScript、PHP、Lua。 このような言語では、原則として、オブジェクトには、型にキャストするときに呼び出される特別なメソッドがあります。 たとえば、PHPには_toString()メソッドがあり、JavaScriptには同じ名前のメソッドがありますが、アンダースコアはありません--toString()。 これらのメソッドは、オブジェクトが文字列型にキャストされるときに呼び出されます。 このようなメソッドは、マジックと呼ばれることもあります(暗黙のプロセスは常にマジックです)。

これらのカテゴリはすべて重複していることに注意することが重要です。 これらのカテゴリに基づいて、JavaScriptが動的に暗黙的に入力されていることがわかります。 そして、私たちが誇張して話す場合、言語の性質は次のように説明できます。理解できない状況では、すべてをプリミティブに、主に線に持っていきます。 実際にはすべてがもう少し複雑ですが、ここでは詳しく説明しません。

「なぜタイピングが必要なのですか?」 -あなたは尋ねるかもしれません。 JavaScriptはそれなしで20年間うまく生きてきました。 答えは簡単です。複雑なエンタープライズレベルの問題を解決するためにJavaScriptが使用されたことはありません。 現在、この言語はブラウザを超えて、バックエンドの領域に入りました。 大規模なアプリケーションを作成する場合、キャストに関連することが多いエラーをキャッチすることが困難になります。

JavaScriptアドイン

JavaScriptはクライアント側(ブラウザー内)で実行されるため、問題を解決するためのオプションの1つは、言語(JSにコンパイルされる方言)を作成することです。 アセンブラとして機能します。

TypeScript、Dart、AtScriptなどの言語が登場し、静的な強い型付け、さらには実行時の型チェックも追加されています(ただし、これによりオーバーヘッドが追加されます)。 これらの言語はすべて、型を追加するだけでなく、構文糖衣構文、またはJSで記述された独自のVM実装も追加します。

ジャーナル「システム管理者」、2015年の第1-2号、86〜88ページの記事全体をお読みください。

この号のPDF版は当店から購入できます。

  1. FlowのWebサイトはhttp://flowtype.orgです。

と接触している

これは、JavaScriptアプリケーションのすべてのモジュールを含む依存関係グラフを生成するモジュラーラッパーです。 Webpackは、ブラウザをロードするためにモジュールを1つ以上の小さなパッケージにパッケージ化します。 さらに、Webpackはモジュール間の依存関係を分析し、リソース(アセット)を生成するため、タスクランチャーとして使用できます。 プロジェクトでのWebpackの使用について詳しくは、をご覧ください。

  • Gruntは、時間のかかる反復的で時間のかかるタスクを自動化するように設計されたタスクランナーです。 そのソフトウェアエコシステムには、膨大な数のプラグイン(6000以上)があります。
  • Gulpは、単なる別のタスクマネージャーではなく、興味深いアプローチを備えたツールです。JavaScriptのタスクを関数として定義し、面倒なタスクを自動化して、広範なソフトウェアエコシステム(2,700を超えるプラグイン)を提供し、透明性と制御を向上させます。プロセスを超えて。
  • Browserifyを使用すると、ソフトウェア開発者はブラウザでNodeJSスタイルのモジュールを使用できます。 依存関係を定義すると、BroweserifyはそれをすべてきちんとしたJSファイルにパックします。
  • Brunch.ioは、スピードとシンプルさに焦点を当てたツールです。 簡単な構成と詳細なドキュメントが付属しており、すぐに使い始めることができます。 Brunchは、CSSスタイルシートとともにJSファイルのマップを自動的に生成するため、クライアント側でのデバッグが容易になります。
  • Yeomanは、ほとんどすべてのプログラミング言語(JavaScript、Python、C#、Javaなど)で使用できる多用途のツールです。 豊富なソフトウェアエコシステム(6200以上のプラグイン)を備えたこの基本的なコード生成システムは、Webアプリケーションの開発に使用されます。 Yeomanを使用すると、既存のプロジェクトを維持および改善することを忘れずに、新しいプロジェクトをすばやく作成できます。
  • IDEおよびコードエディタ

    • Swaggerは、APIを記述するための一連のルールとツールです。 このツールは言語に依存しないユーティリティです。 つまり、Swaggerは、人間とマシンの両方が読み取れる明確なドキュメントを作成し、APIに依存するプロセスを自動化できるようにします。
    • JSDocは、JavaScriptソースコードからのコメントから複数ページのテキストドキュメント(HTML、JSON、XMLなど)を自動的に生成するツールのセットです。 このアプリケーションは、大規模なプロジェクトの管理に役立ちます。
    • jGrouseDoc(jGD)は、開発者がJavaScriptソースコードからのコメントからAPIを生成できるようにする柔軟なオープンソースツールです。 jGDは、変数と関数だけでなく、名前空間、インターフェース、パッケージ、その他の要素も文書化します。
    • YUIDocはNodeJSで書かれたアプリケーションです。 JavadocやDoxygenと同様の構文を使用します。 また、ライブプレビューのサポート、拡張言語のサポート、高度なマークアップも備えています。
    • Doccoは、「文学的な」CoffeeScriptで書かれた無料のドキュメントツールです。 コードが散在するコメントを表示するHTMLドキュメントを作成します。 このツールはJavaScriptだけでなく他の言語もサポートしていることに注意してください。 たとえば、Python、Ruby、Clojureなどです。

    テストツール

    JavaScriptテストツールは、開発中にバグをキャッチして、将来のユーザーのバグを回避するように設計されています。 カスタムアプリケーションの複雑さが増すにつれて、自動テストはアプリケーションのパフォーマンスを向上させるだけでなく、企業が予算を維持するのにも役立ちます。

    • Jasmineは、JSコードをテストするためのビヘイビア駆動開発(BDD)フレームワークです。 外部依存関係はなく、DOMを実行する必要はありません。 Jasmineには、テストをより速く簡単にするクリーンでわかりやすい構文があります。 このフレームワークは、PythonおよびRubyコードのテストにも使用できます。
    • Mochaは、ブラウザーのNode.jsで実行される機能テストフレームワークです。 テストを一貫して実行し、柔軟で正確なレポートを提供して、非同期テストを楽しく簡単にします。 モカは、テスト結果を確認するためにチャイと組み合わせて使用​​されることがよくあります。
    • PhantomJSは、フロントエンドテストや単体テストによく使用されます。 これが「ヘッドレス」WebKitのようなものであることを考えると、スクリプトの実行ははるかに高速です。 また、さまざまなWeb標準のサポートが組み込まれています。 たとえば、JSON、Canvas、DOM処理、SVGおよびCSSセレクター。
    • Protractorは、AngularJSおよびAngularアプリケーションをテストするためにNode.jsで記述されたエンドツーエンドのテストフレームワークです。 WebDriverJSの上に構築され、カスタムドライバーとインラインイベントを使用してエンドユーザーなどのアプリケーションを検証します。

    デバッグツール

    コードのデバッグは、JavaScript開発者にとって面倒で時間のかかるプロセスです。 デバッグツールは、数千行のコードを操作する場合に特に便利です。 デバッグツールの多くは、かなり正確な結果を提供します。

    • JavaScriptデバッガーは、Mozilla Developer Community(MDN)のツールであり、ブラウザー間でコードをデバッグするためのスタンドアロンWebアプリケーションとして使用できます。 Firefoxは、ローカル機能とリモート機能、およびFirefox forAndroidを使用してAndroidデバイスでコードをデバッグする機能を提供します。
    • Chrome Dev Toolsは、JavaScriptコードのデバッグ、CSSの編集、アプリケーションのパフォーマンスのテストを行うためのいくつかのユーティリティを含むツールのセットです。
    • ng-inspectorは、開発者がAngularJSアプリケーションを作成、理解、デバッグするのに役立つように設計されたクロスブラウザー拡張機能です。 このユーティリティには、リアルタイムの更新、DOMの強調表示、リージョン、モデル、およびアプリケーションの他の要素への直接アクセスが付属しています。
    • Auguryは、GoogleChromeブラウザとAngular2アプリケーションのデバッグ用の拡張機能です。これにより、Angular 2アプリケーションの開発者は、アプリケーションの構造とパフォーマンスを直接分析し、変更を検出できます。

    セキュリティツール

    • Snykは、JavaScript、Java、およびRubyアプリケーションの既知の脆弱性を検出、修正、および防止するための商用ツールです。 このサービスには独自の脆弱性データベースがあり、NSPおよびNISTNVDからデータを取得します。 同社が提供するパッチとアップデートにより、開発者はセキュリティリスクを予測できます。
    • Node Security Projectは、依存関係のスキャンと脆弱性の検出に役立つツールを提供します。 NSPは、npmモジュールスキャンに基づいて構築された独自のデータベースと、NIST NVD(National Vulnerability Database)などの一般的なデータベースからのデータを使用します。 さらに、NSPはGitHubプルリクエストおよびCIソフトウェアとの統合を提供します。 Node.jsアプリケーションの脆弱性を排除するためのリアルタイムのスキャン、警告、および推奨事項もあります。
    • RetireJSは、オープンソースの依存関係チェッカーです。 コマンドラインスキャナー、Gruntプラグイン、FirefoxおよびChrome拡張機能、Burpプラグイン、OWASPZAPなどのさまざまなコンポーネントが含まれています。 Retirejsは、NIST NVDや、バグトラッカー、ブログ、メーリングリストなどの他のソースから脆弱性情報を収集します。
    • Gemnasiumは、無料トライアル付きの商用ツールです。 Ruby、PHP、Bower(JavaScript)、Python、npm(JavaScript)などのさまざまなテクノロジーとパッケージをサポートしています。 Gemnasiumセキュリティツールには、自動更新、リアルタイムアラート、セキュリティ通知、Slackサービスとの統合などの便利な機能が付属しています。
    • OSSIndexは、さまざまなエコシステム(Java、JavaScript、.NET / C#)と、NuGet、npm、Bower、Chocolatey、Maven、Composer、Drupal、MSIなどの多くのプラットフォームをサポートしています。 National Vulnerability Database(NVD)とレビューから脆弱性情報を収集します。 また、コミュニティメンバーからの情報も処理します。

    分析およびコード最適化ツール

    コードの品質をチェックするには、通常、機能テストと単体テストに目を向けます。 ただし、開発者がコードの品質とコーディング標準への準拠を確認できる別のアプローチ、つまり静的コード分析があります。

    現在、最新のソフトウェアは、開発中に静的コードを分析するためのツールを組み合わせて、低品質のコードを本番環境に移行することから除外しています。

    • JSLintは、JavaScriptコードの品質をチェックするためのWeb分析ツールです。 ソースで問題を検出すると、問題の説明とコード内のおおよその場所を含むメッセージを返します。 JSLintは、いくつかのスタイルノルムを解析し、構文エラーや構造上の問題を明らかにすることができます。
    • JSHintは、JSコードのバグや潜在的な問題を検出するための柔軟なコミュニティ主導のツールであり、JSHintはJSLintのフォークです。 この静的コード分析ツールの主な目的は、複雑なプログラムで作業するJavaScript開発者を支援することです。 構文エラー、暗黙的なデータ型変換、または変数の欠落を検出できます。 ただし、アプリケーションの速度と正確さを検出することも、アプリケーションのメモリの問題を特定することもできません。 JSHintはJSLintのフォークです。
    • ESLintは、JSXおよびJavaScriptWebアプリケーション用のオープンソースリンターです。 疑わしいパターンを見つけたり、特定のスタイルに一致しないコードを見つけたりするのに役立ちます。 これにより、開発者はJSコードを実行せずにエラーを検出できるため、時間を節約できます。 Node.jsで記述されたこのツールは、応答性の高いランタイムとnpmを介したスムーズなインストールを提供します。
    • Flowは、Facebookによって開発された静的なJavaScriptコードコントローラーです。 静的型アノテーションを使用して、コードのエラーをチェックします。 タイプは開発者によって設定されたパラメーターであり、Flowはソフトウェアのコンプライアンスをチェックします。

    バージョン管理ツール

    • 近年、Gitは小規模プロジェクトと大規模プロジェクトの両方で広く使用されているバージョン管理システムになりました。 この無料のユーティリティは、優れた速度と効率を提供します。 その人気は、分散システムとさまざまなタイプのコントロール、およびコミットが完了する直前にバージョンをプレビューしてフォーマットできるステージング領域によるものです。
    • Subversionツール(SVN)は絶大な人気を博しており、PythonApacheやRubyなどのオープンソースプロジェクトやプラットフォームで今でも広く使用されています。 このCVSには、さまざまな操作(名前の変更、コピー、削除など)、マージ、ファイルロックなどを管理するための多くの機能が付属しています。

    パッケージおよび依存関係管理ツール

    最高のJavaScript開発ツールのリストはどんどん増えていきます。 この記事では、高品質の製品の基礎となる人気のある信頼性の高いツールのみを見てきました。

    そして、Netologyの教師は、EcmaScript6に関する一連の記事をブログに書きました。 最初の部分では、Iroh.jsを使用したEcmaScriptでの動的コード分析の例を見ていきます。

    静的および動的コード分析

    コード分​​析ツールは、コードの作業におけるエラーや特殊性を検出および検出するための便利なツールです。 コード分​​析は静的および動的にすることができます。 前者の場合、ソースコードは実行せずに解析および分析され、後者の場合、実行は制御されたサンドボックス環境で行われ、実行中にアプリケーションの要素に関するメタ情報が提供されます。

    結論

    Iroh.jsは、EcmaScriptで動的コード分析を行うための強力で機能的なツールです。 このツールは、コールグラフの作成、変数とオブジェクトの実際のタイプと値の表示などのコード分析と、イベントに基づくコード修正を含むオンザフライでのコード変更の両方に使用できます。

    動的分析はかなり複雑な方法ですが、EcmaScriptの場合、ダックタイピング、ホストオブジェクトの存在、およびコードの動作をその場で変更できるネイティブ関数が存在するため、これがコードを分析およびデバッグする唯一の方法です。実行時。 Iroh.jsは、コードを使用して、値をエクスポートするためにコードを変更することなく、機能テストを作成することもできます。

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

    静的アナライザーは、コードを実行する前に、コードを調べてエラーを見つけます。 構文チェック(スペースの代わりにタブなど)を適用するなどの単純なチェックと、関数が過度に複雑でないことをチェックするなどのよりグローバルなチェックを実行します。 静的アナライザーは、テスト中に検出できないバグも探します。たとえば、===ではなく==です。


    大規模なプロジェクトや大規模なチームで作業する場合は、このような「単純な」バグを見つけるのに少し役立つことがありますが、実際には、見た目ほど単純ではないことがわかります。


    JSLint、JSHintおよびClosureコンパイラ


    JavaScriptの静的アナライザーには、JSLint、JSHint、およびClosureCompilerの3つの主要なオプションがあります。



    JSLintは、JavaScript用の最初の静的アナライザーでした。 公式サイトで実行することも、ローカルファイルで実行できるアドオンの1つを使用することもできます。 JSLintは多くの重要なバグを見つけますが、それは非常に困難です。 代表的な例を次に示します。



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

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



    予期しない「++」。
    「var」宣言を関数の先頭に移動します。

    最初の問題は、ループ条件での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はWebサイトから実行できますが、ほとんどの場合、Node.jsを使用してローカルコマンドラインツールとしてJSHintをインストールすることをお勧めします。 JSHintをインストールしたら、次のようなコマンドを使用してファイルでJSHintを実行できます。



    jshint test.js

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


    クロージャーコンパイラ


    GoogleのClosureCompilerは、まったく別の種類のプログラムです。 その名前が示すように、それはテストプログラムであるだけでなく、コンパイラでもあります。 これはJavaで書かれており、MozillaのRhinoパーサーに基づいています。 クロージャーコンパイラには、基本的なコードチェックを実行するための単純なモードと、追加のチェックを実行して特定のビュー定義を適用するためのより複雑なモードが含まれています。


    クロージャコンパイラはJavaScriptコードのエラーを報告しますが、JavaScriptの縮小バージョンも生成します。 コンパイラーは、空白、コメント、および未使用の変数を削除し、長い式を単純化して、スクリプトを可能な限りコンパクトに保ちます。


    Googleは、コンパイラの非常に基本的なバージョンをネット上で利用できるようにしましたが、ClosureCompilerをダウンロードしてローカルで実行することをお勧めします。


    クロージャコンパイラは、コードをチェックした後、ファイルのリストを1つの縮小ファイルに出力します。 したがって、compiler.jarファイルをダウンロードして実行できます。



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

    適切な検証プログラムの選択


    私のプロジェクトでは、ClosureCompilerとJSHintを組み合わせています。 クロージャコンパイラはミニファイと基本的な検証を行いますが、JSHintはより複雑なコード分析を行います。 これらの2つのプログラムは連携して機能し、それぞれが他のプログラムでは不可能な領域をカバーします。 さらに、JSHint拡張機能を使用してカスタムバリデーターを作成できます。 私が作成したジェネリックプログラムの1つは、プロジェクトに含めるべきではない関数の呼び出しなど、必要のない特定の関数をテストします。


    チェックするいくつかのプログラムについて説明したので、悪いコードのいくつかを分解してみましょう。 これらの6つの例はそれぞれ、書く価値のないコードであり、コードバリデーターがあなたを救うことができる状況です。


    この記事ではほとんどの例でJSHintを使用していますが、ClosureCompilerは通常同様の警告を生成します。


    ==または===?


    JavaScriptは動的に型付けされた言語です。 コードを書くときに型を定義する必要はなく、起動時に存在します。


    JavaScriptは、このような動的型を操作するための2つの比較演算子==と===を提供します。 例を挙げてこれを見てみましょう。



    var n = 123;
    var s = "123";

    if(n == s)(
    警告( "変数は等しい");
    }

    if(n === s)(
    警告(「変数は同一です」);
    }

    比較演算子 == JavaScriptがルーツを持つC言語の名残です。 その使用はほとんどの場合間違いです:型とは別に値を比較することは、開発者が実際にやりたいことはめったにありません。 実際、「123」という数字は「123」という文字列とは異なります。 これらの演算子は、スペルを間違えやすく、さらに読み間違えやすくなっています。 JSHintでこのコードを確認すると、次のようになります。

    test.js:9行目、12列目、「===」が必要で、代わりに「==」が表示されました。

    未定義の変数と後期定義


    いくつかの簡単なコードから始めましょう:



    機能テスト () (
    var myVar = "Hello、World";
    console.log(myvar);
    }

    バグを見ますか? 私は毎回この間違いを犯します。 このコードを実行すると、エラーが発生します。



    ReferenceError:myvarが定義されていません

    問題をもう少し複雑にしましょう。



    機能テスト () (
    myVar = "Hello、World";
    console.log(myVar);
    }

    このコードを実行すると、次のようになります。



    こんにちは世界

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

    test.js:3行目、17列目、「myvar」が定義されていません。

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



    test.js:2行目、5列目、「myVar」が定義されていません。
    test.js:3行目、17列目、「myVar」が定義されていません。

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


    2番目の例の問題は、知らぬ間に微妙で複雑です。 変数myVarはスコープから消え、グローバルスコープに移動しました。 これは、テスト関数が実行された後でも存在し、値がHello、Worldになることを意味します。 これはグローバルスコープ汚染と呼ばれます。


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



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

    Hello、Worldが引き続き表示されます。 変数myVarは、テンプレートのようにコード全体でハングします。これにより、varの記述を忘れたために、リリース前に一晩中探す複雑なバグが発生します。


    このエントリはフルテキストRSSサービスを通過しました-これがあなたのコンテンツであり、「他の誰かに読んでいる」サイトの場合は、http://ift.tt/jcXqJWのFAQを読んでください。


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

    静的アナライザーは、コードを実行する前に、コードを調べてエラーを見つけます。 構文チェック(スペースの代わりにタブなど)を適用するなどの単純なチェックと、関数が過度に複雑でないことをチェックするなどのよりグローバルなチェックを実行します。 静的アナライザーは、テスト中に検出できないバグも探します。たとえば、===ではなく==です。

    大規模なプロジェクトや大規模なチームで作業する場合は、このような「単純な」バグを見つけるのに少し役立つことがありますが、実際には、見た目ほど単純ではないことがわかります。

    JSLint、JSHintおよびClosureコンパイラ

    JavaScriptの静的アナライザーには、JSLint、JSHint、およびClosureCompilerの3つの主要なオプションがあります。

    JSLintは、JavaScript用の最初の静的アナライザーでした。 公式サイトで実行することも、ローカルファイルで実行できるアドオンの1つを使用することもできます。 JSLintは多くの重要なバグを見つけますが、それは非常に困難です。 代表的な例を次に示します。

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

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

    予期しない「++」。 「var」宣言を関数の先頭に移動します。

    最初の問題は、ループ条件での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はWebサイトから実行できますが、ほとんどの場合、Node.jsを使用してローカルコマンドラインツールとしてJSHintをインストールすることをお勧めします。 JSHintをインストールしたら、次のようなコマンドを使用してファイルでJSHintを実行できます。

    Jshint test.js

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

    クロージャーコンパイラ

    GoogleのClosureCompilerは、まったく別の種類のプログラムです。 その名前が示すように、それはテストプログラムであるだけでなく、コンパイラでもあります。 これはJavaで書かれており、MozillaのRhinoパーサーに基づいています。 クロージャーコンパイラには、基本的なコードチェックを実行するための単純なモードと、追加のチェックを実行して特定のビュー定義を適用するためのより複雑なモードが含まれています。

    クロージャコンパイラはJavaScriptコードのエラーを報告しますが、JavaScriptの縮小バージョンも生成します。 コンパイラーは、空白、コメント、および未使用の変数を削除し、長い式を単純化して、スクリプトを可能な限りコンパクトに保ちます。

    Googleは、コンパイラの非常に基本的なバージョンをネット上で利用できるようにしましたが、ClosureCompilerをダウンロードしてローカルで実行することをお勧めします。

    クロージャコンパイラは、コードをチェックした後、ファイルのリストを1つの縮小ファイルに出力します。 したがって、compiler.jarファイルをダウンロードして実行できます。

    Java -jarcompiler.jar --js_output_file compress.js --js test1.js --js test2.js

    適切な検証プログラムの選択

    私のプロジェクトでは、ClosureCompilerとJSHintを組み合わせています。 クロージャコンパイラはミニファイと基本的な検証を行いますが、JSHintはより複雑なコード分析を行います。 これらの2つのプログラムは連携して機能し、それぞれが他のプログラムでは不可能な領域をカバーします。 さらに、JSHint拡張機能を使用してカスタムバリデーターを作成できます。 私が作成したジェネリックプログラムの1つは、プロジェクトに含めるべきではない関数の呼び出しなど、必要のない特定の関数をテストします。

    チェックするいくつかのプログラムについて説明したので、悪いコードのいくつかを分解してみましょう。 これらの6つの例はそれぞれ、書く価値のないコードであり、コードバリデーターがあなたを救うことができる状況です。

    この記事ではほとんどの例でJSHintを使用していますが、ClosureCompilerは通常同様の警告を生成します。

    ==または===?

    JavaScriptは動的に型付けされた言語です。 コードを書くときに型を定義する必要はなく、起動時に存在します。

    JavaScriptは、このような動的型を操作するための2つの比較演算子==と===を提供します。 例を挙げてこれを見てみましょう。

    変数n = 123; var s = "123"; if(n == s)(alert( "変数が等しい");)if(n === s)(alert( "変数が同一");)

    比較演算子 == JavaScriptがルーツを持つC言語の名残です。 その使用はほとんどの場合間違いです:型とは別に値を比較することは、開発者が実際にやりたいことはめったにありません。 実際、「123」という数字は「123」という文字列とは異なります。 これらの演算子は、スペルを間違えやすく、さらに読み間違えやすくなっています。 JSHintでこのコードを確認すると、次のようになります。

    Test.js:9行目、12列目、「===」が必要で、代わりに「==」が表示されました。

    未定義の変数と後期定義

    いくつかの簡単なコードから始めましょう:

    関数テスト()(var myVar = "Hello、World"; console.log(myvar);)

    バグを見ますか? 私は毎回この間違いを犯します。 このコードを実行すると、エラーが発生します。

    ReferenceError:myvarが定義されていません

    問題をもう少し複雑にしましょう。

    関数テスト()(myVar = "Hello、World"; console.log(myVar);)

    このコードを実行すると、次のようになります。

    こんにちは世界

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

    Test.js:3行目、17列目、「myvar」が定義されていません。

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

    Test.js:2行目、5列目、「myVar」が定義されていません。 test.js:3行目、17列目、「myVar」が定義されていません。

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

    2番目の例の問題は、知らぬ間に微妙で複雑です。 変数myVarはスコープから消え、グローバルスコープに移動しました。 これは、テスト関数が実行された後でも存在し、値がHello、Worldになることを意味します。 これはグローバルスコープ汚染と呼ばれます。

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

    Console.log( "myVar:" + myVar);

    Hello、Worldが引き続き表示されます。 変数myVarは、テンプレートのようにコード全体でハングします。これにより、varの記述を忘れたために、リリース前に一晩中探す複雑なバグが発生します。