ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScript における変数のスコープとメモリの問題を理解する

JavaScript における変数のスコープとメモリの問題を理解する

php是最好的语言
php是最好的语言オリジナル
2018-08-03 10:17:571152ブラウズ

変数のスコープとメモリの問題

1. 基本型と参照型の値

基本型は単純なデータセグメント (5 つの値型) ですが、参照型はオブジェクト (オブジェクトへの参照を操作する) です。

1.1 変数値のコピー

参照型はコピー時に実際に関数ポインタを渡します。このオブジェクトを変更すると、2 つの変数は実際にはヒープ メモリ内の同じオブジェクトを参照します。変数も同期的に変更されます。

1.2 パラメータの受け渡し

関数のパラメータはすべて値によって渡されます。実際のところ、この言葉はまだ抽象的だと思います。こうまとめると良いでしょう。関数に渡される変数が値型の場合、関数に渡される元の変数のは関数内部の影響で変化しません。関数に渡される変数が参照型(オブジェクト)の場合、関数に渡される元の変数のreferenceは関数内部の影響で変化しません。実際、ここで理解するのは簡単ではありません。たとえば、

        var obj = {
            name: 'andy'
        }

        function ChangeObj(val) {
            val.age = '25'
            val = {
                name:'zakas',
                age:40
            }
            return val;
        }
        ChangeObj(obj); // {name:'zakas',age:40}
        console.log(obj) // {name:'andy',age:25}

上の例では、関数が渡されると、関数内の val のメモリ アドレスが変更されます。 Reference の場合、val の参照は obj になります。reference と val の適用が変更されると、それに応じて obj の参照も変更されるため、obj の結果も {name:'zakis',age:40} になるはずです。値によって渡された場合、obj は val への参照に割り当てられますが、val 参照への変更は obj の参照アドレスに影響しません。

関数の仮パラメータは、関数スコープ内のローカル変数です。関数の実行が終了すると破棄されます。

1.3 検出型

instanceof は、参照型のより明示的な検出を実行できます。したがって、instanceof の値の型は常に false であり、そのメソッドを使用して値の型を検出する必要はありません。 instanceof は Array オブジェクトと RegExp のみを区別できます

2. 実行環境

各実行環境には 変数オブジェクト の概念が非常に重要です。これは、スコープ内で定義されたすべての変数の大きなコレクションです。各実行環境には、定義したすべての変数を保存する変数オブジェクトがありますが、この変数オブジェクトにはアクセスできませんが、パーサーがデータを処理するときに使用されます。背景にあります。

    function A() {
        var tempA;
        function B() {
            var tempB;
            function C() {
                var tempC
            }
        }
    }

B() のスコープ チェーンには 3 つのオブジェクトが含まれており、1 つは独自の変数オブジェクト、A の変数オブジェクトとグローバル変数オブジェクトです。 A() のスコープ チェーンには、A() 自身の変数オブジェクトとグローバル変数オブジェクトの 2 つのオブジェクトが含まれています。したがって、A は B の変数にはアクセスできませんが、独自の変数とグローバル変数のみにアクセスできます。ただし、B は独自の変数にアクセスできるだけでなく、A 内の変数やグローバル スコープにもアクセスできます。

2.1 スコープチェーンを拡張する

with

With は、現在のスコープの上に新しい変数オブジェクトを作成することと同じです。例:

    var obj = {
        name:'andy',
        sex:'man',
        hobby:'game'
    }
    function fn() {
        with(obj) {
            fnName = name;
            fnSex = sex;
            fnHobby = hobby;
        }
        console.log(fnName,fnSex,fnHobby) // andy,man,game
    }
    fn()

With メソッドはパフォーマンスの重大な損失を引き起こすため、一般的に使用することはお勧めできません

2.2 ブロックレベルのスコープはありません

この概念、機能、違い、最も一般的な質問を理解しておく必要があります:

for(var i =0 ; i < 10 ; i++ ) {
    setTimeout(function(){
        console.log(i);
    },0)
}

理解するために この問題の前提として、タイマーは非同期であることをまず知っておく必要があります。たとえそれが0であっても、最初にキャッシュ領域に配置され、他のプログラムが上から下まで実行を完了した後に呼び出されなければなりません。したがって、他のプログラムが上から下に実行された後、ブロックレベルのスコープがないため、i はグローバルであり 10 になっているため、10 個の 10 が出力されます。 i をブロックレベルのスコープを持つ let に変更すると、問題は解決します。

for(let i =0 ; i < 10 ; i++ ) {
    setTimeout(function(){
        console.log(i);
    },0)
}

2.3 ガベージコレクション

JavaScriptには自動ガベージコレクション機構があります

値を使用するプロセスは、実際には変数によって割り当てられたメモリの書き込みと読み取りに相当します。 JavaScript は変数を作成するプロセス中にメモリを割り当て、変数が使用されない場合は自動的に解放します。ただし、この自動性が混乱の原因となっています。メモリの問題を気にしすぎるのは間違いです。

原則: ガベージ プロセッサはデフォルトで定期的に検出し、未使用の変数を見つけてメモリを解放します。
リサイクル戦略: ローカル環境では、関数が呼び出された後、ガベージ コレクターはどの変数が役に立ち、どの変数が役に立たないかを追跡します。役に立たない変数については、メモリのリサイクルの準備としてマークを付けます。ただし、マーク方法は次のとおりです。通常、他に 2 つの戦略があります:

  • マークのクリア: 2012 年以降、すべてのブラウザーはガベージ コレクションにマーク クリア メソッドを使用するようになり、js ガベージ コレクションのすべての改良もアルゴリズム最適化のためのマーク クリア メソッドに基づいています。

  • 参照カウント: これには深刻な循環参照の問題があるため、基本的には使用されなくなりました。

したがって、メモリ消費量が少ないプログラムを書くことは、高パフォーマンスのページにとって非常に重要なポイントです。したがって、プログラムを作成するとき、データが不要になったら、逆参照

のために null に設定するのが最善です。関連記事:

JavaScript 変数のスコープとメモリの問題 (2)

Li Yanhui Javascript ビデオ チュートリアル

以上がJavaScript における変数のスコープとメモリの問題を理解するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。