1

この記事によると

http://www.mediaevent.de/javascript/globale-lokale-variablen.html

グローバル変数は JS ではかなり危険です。

ドイツ語で申し訳ありませんが、記事の 2 つの主要なステートメントを指摘します。

最初の文は、head ステートメントの 2 番目の段落にあります。

「JS では、名前を介して他のスクリプトからアクセスされる可能性があるため、グローバル変数は危険です」などと書かれています。

しかし、この記事では、これはランダムに発生する可能性があるようです。それは確かに期待される動作ではありませんね。

しかし、私がもっと恐ろしいのは、最後から 2 番目の文です。グローバル変数を宣言する関数を複数回呼び出すと、メモリリークが発生することが予測されます。しかし、名前がまだ同じである場合、どうしてこれが起こるのでしょうか? 同じ名前でグローバルに宣言された複数の変数がどのように存在する可能性がありますか? それとも、この記事はおそらく「半知識」の誰かによって書かれているのでしょうか? それとも、グローバルとローカルの違いにまったく慣れていない人に宛てたものでしょうか? または、JS は本当にこのように動作していますか?

具体的な例:

私のページにログインした人に、ランダムに生成されたトークンを作成してもらい、ログインをクリックして送信してもらいたいです。他のボタンごとに、このトークンが別の機能によってアクセスされ、それを送信するだけで、新しいログインのためにキーが再生成されるようになります。

そのキーについては、ある関数によって宣言され、別の関数によって返されるグローバル変数を使用することを考えていました。しかし、キーを複数回生成/再生成する可能性があるため、これによりメモリリークが発生しますか? それとも、私が言及しているこの記事は、おそらくただ脚色しただけなのでしょうか? これが実際に JS の動作である場合、私の場合、さまざまな関数から変数にアクセスできるようにする良い方法は何でしょうか?

4

3 に答える 3

9

グローバルの問題はメモリではなく、パフォーマンスでもありません。

グローバルの問題はまったく異なります。問題は、それらがグローバルな状態を導入することと、スクリプトが名前空間にバインドされていないことです。

これらの問題を 1 つずつ見ていきましょう。

グローバルな状態を持つ

ここが最大の問題です。コーディングでは、モジュールの依存関係が明示的であり、コード間の通信が非常に明確である必要があります。

グローバル変数がある場合、コードのどの部分でその変数が使用されているかはほとんど明確ではなく、コードのどの部分でそれが必要で、どの部分で必要でないかわかりません。

ZooプロジェクトがありBathe、動物を掃除するサービスがあるとしましょう。それを必要とする各動物に渡す代わりに、Bathe私はそれをグローバル名前空間に持っていて、単に を呼び出しますBathe(myAnimal)

今、私は自分の動物園を再構築したいと考えており、それを最適化したいので、どの動物が水浴びを必要としているかを知りたいと思っています。コード全体を調べる以外に、それを知る方法はありません。私のキリンが入浴する必要があるかどうかを確認するには、キリン クラスのコード全体を読む必要があります。代わりに、Giraffe を使用したり、Giraffe 内で作成したりする代わりに、Giraffe のコンストラクターに渡しBatheた場合 (依存性注入と呼ばれる概念)、署名を読み取るだけで、Giraffe が入浴する必要があることがわかります。

これはさらに悪化する可能性があります。状態がある場合はどうなりますか? 実際に複数の場所でグローバル変数を変更すると、追跡が非常に難しくなります。数行以上のコードベースでは、これは、状態が変化していて、誰がそれを変更しているかを明確に示していないことを意味します。

これが、グローバルを完全に避けるべき主な理由です。

スクリプトは名前空間にバインドされていません

ページに 2 つのスクリプトがあり、最初のスクリプトAがグローバル名前空間で変数を宣言する場合、2 番目のスクリプトはその変数にアクセスできます。これは、スクリプトがこのようにやり取りできるため便利ですが、スクリプトが互いのコードをオーバーライドし、あいまいな方法で通信できることを意味するため、非常に有害です。

もちろん、browserify やRequireJSなどのモジュール ローダーを使用すると、これは完全に軽減されます。つまり、スクリプト全体で 2 つのグローバルのみが公開さrequiredefine、スクリプトの読み込みはローダーを介して行われます。

このようにして、コードの独立した部分が相互作用する方法が明確に定義されます。これは、グローバル オブジェクトで変数を作成することを妨げるものではありませんが、統一された方法で作成する必要性を軽減するのに役立ちます。

セキュリティ上の注意

もちろん、クライアント側のすべてが危険にさらされています。クライアントは任意のコードを実行できるため、安全でないブラウザーのクライアント側 JavaScript でセキュリティやそのようなことを行うことはできません (つまり、外部で何も防止していません)。あなたのコードでそれを読んでください。

于 2013-10-11T08:48:18.333 に答える
6

グローバル変数には 3 つの大きな問題があります。

  1. 名前の衝突
  2. コードの複雑さ
  3. ガベージコレクション

名前の衝突

グローバル スコープに変数を持つことの問題点は、そのスコープ内にあるものを制御しにくいことです。あなたのコードは ga_ 変数をグローバルに使用しており、正常に動作しますが、同じ変数を使用する Google アナリティクス スニペットを追加すると、予期せずエラーが発生し、ショッピング カートが 3 ページ中 2 ページの読み込みに失敗する理由を理解するのが非常に困難になる場合があります。

コードを IIFE でラップして、変数がグローバル スコープに含まれないようにすることができる場合は、そうする必要があります。明らかに、実際にコードをグローバルにアクセスできるようにしたい場合があります (例: jQuery ライブラリ)。そのような場合は、関連する名前を付けて、すべてのものを単一の名前空間 (jQuery) に保持することをお勧めします。

コードの複雑さ

通常、コードを分割して、個々の部分が相互に最小限の相互作用をするようにすることをお勧めします。相互作用する部分が多ければ多いほど、変更を加えたり、バグの発生源を追跡したりすることが難しくなります。明らかに、グローバル変数はどこからでもアクセスできるため、グローバル変数にアクセスするコードに問題がある場合、その変数のすべての使用を検査する必要があり、これは非常に大きな苦痛になる可能性があります。これらの苦痛を避けるためにすべきことは、変数を可能な限りローカルに保ち、コードの一部をカプセル化して、特定のインターフェイスを介した場合を除いて相互にやり取りできないようにすることです。

メモリリーク

JavaScript では、ガベージ コレクション プロセスをほとんど制御できません。保証されているのは、変数にアクセスできる場合、ガベージ コレクションが行われないということだけです。これは、何かをガベージ コレクションしたい場合は、それ以上アクセスできないようにする必要があることを意味します。数値を保持するグローバルi変数は大したことではありませんが、グローバル変数が時間の経過とともにますます多くのプロパティを保持する場合に @Boluc Papuaccoglu が述べたように (たとえば、XHR リクエストの配列、または作成された DOM オブジェクトの配列)、メモリ消費量が大きくなります。

これらの状況はすべて最悪のシナリオであり、小さなアプリケーションではおそらく問題はありません。これらの推奨事項は、プログラミングの学習を開始するときに最も価値があります。これは、良い習慣を身につけるためであり、複雑なアプリケーションに取り組んでいるときに、デバッグや困難な改善に費やされる時間とお金を節約できるからです。

于 2013-10-11T08:59:02.887 に答える