JavaScriptのスタックとコピーの詳細な説明

JavaScriptのスタックとコピーの詳細な説明

1. スタックの定義

1. スタックは特殊な線形リストです。その特殊性は、データ要素の挿入と削除の操作が線形リストの一方の端でのみ実行できることです。

結論: 後入れ先出し (LIFO)、略して LIFO 線形リスト。

スタックの用途には、数値システムの変換、文法および語彙の解析、式の評価などがあります。

2. キューも操作が制限された線形テーブルです。その操作制限はスタックとは異なります。両端に制限があります。挿入はテーブルの一方の端でのみ実行でき(inのみ、outは不可)、削除はテーブルのもう一方の端でのみ実行できます(outのみ、inは不可)。削除を許可する端は後方と呼ばれ、挿入を許可する端は前方と呼ばれます。キューの動作原理は先入れ先出しであるため、キューはFIFOテーブル(First In First Out)とも呼ばれます。

スタックとキューも線形リストであるため、シーケンシャル スタックとリンク スタックの 2 つのストレージ構造があります。これら 2 つのストレージ構造の違いにより、スタックの基本操作を実装するアルゴリズムも異なります。

2. JSスタックの調査

1. スタックとヒープ

スタックは自動的に割り当てられたメモリ空間であり、システムによって自動的に解放されます。一方、ヒープは動的に割り当てられるメモリですが、そのサイズは不確定であり、自動的に解放されません。

2. 基本型と参照型

(1)基本型:スタックメモリに格納される単純なデータセグメントであり、割り当て可能なデータサイズとメモリ空間サイズは固定されている。
5 つの基本データ型は、Undefined、Null、Boolean、Number、String です。これらは値によって直接保存されるため、直接アクセスできます。

(2)参照型:ヒープメモリに格納されるオブジェクト。変数は実際には別の場所を指すポインタを格納します。各スペースのサイズは異なり、状況に応じて具体的に割り当てる必要があります。

参照型 (オブジェクト、配列、関数など) の値にアクセスする必要がある場合、まずスタックからオブジェクトのアドレス ポインターを取得し、次にヒープ メモリから必要なデータを取得します。

3. 値渡しと参照渡し

メモリ内のヒープ、スタック、変数の型が何であるかを説明した理由は、実際には「浅いコピー」と「深いコピー」が何であるかをよりよく理解するためです。
基本型と参照型の最大の違いは、実際には値渡しとアドレス渡しの違いです。テストケース:

var a = [1,2,3,4,5];
var b = a;
var c = a[0];
アラート(b); //1,2,3,4,5 
アラート(c); //1 
//値を変更する b[4] = 6;
7;
アラート(a[4]); //6
アラート(a[0]); //1

上記から、b のデータを変更すると a のデータも変更されますが、c のデータ値を変更しても a は変更されないことがわかります。
これが値渡しと参照渡しの違いです。 a は配列であり参照型であるため、b に割り当てられると、ヒープ メモリ内のオブジェクトではなく、スタック内のアドレスが渡されます (別の名前を持つ新しい「ポインター」を作成するのと同じです)。そして、c はヒープ メモリから取得され、スタックに格納される単なるデータ値です。したがって、b が変更されると、変更先のアドレスに従って a ヒープに戻りますが、c はスタック内で直接変更されるため、a ヒープ メモリを指すことはできません。

3. コピー

1. 浅いコピー

前述したように、オブジェクトまたは配列を定義する場合、変数にはアドレスのみが格納されることがよくあります。オブジェクト コピーを使用する場合、属性がオブジェクトまたは配列であれば、渡すのはアドレスだけです。したがって、子オブジェクトがこのプロパティにアクセスすると、アドレスに基づいて親オブジェクトが指しているヒープメモリに遡ります。つまり、親オブジェクトと子オブジェクトは関連付けられており、2 つのプロパティ値は同じメモリ空間を指すことになります。

var a = {
         キー1:"11111"
    }
関数Copy(p) {
var c = {};
(変数 i が p 内にある) { 
           c[i] = p[i];
        }
c を返します。
  }
     a.key2 = ['シャオフイ','シャオフイ'];
var b = コピー(a);
   b.key3 = '33333';
     アラート(b.key1); //1111111
     アラート(b.key3); //33333
     alert(a.key3); //未定義

a オブジェクトの key1 属性は文字列であり、key2 属性は配列です。 a が b にコピーされ、12 個の属性すべてが正常にコピーされます。文字列属性 key3 が b オブジェクトに追加されると、b は正常に変更できますが、a では定義されません。これは、子オブジェクトの key3 (基本型) が親オブジェクトに関連付けられていないため、未定義であることを意味します。

b.key2.push("ダフイ");
alert(b.key2); // 小慧、小慧、大慧 alert(a.key2); // 小慧、小慧、大慧

ただし、変更されたプロパティがオブジェクトまたは配列になった場合は、親オブジェクトと子オブジェクトの間に関連付けが発生します。上記のポップアップ結果から、b オブジェクトを変更すると、a と b の key2 属性値 (配列) が変更されたことがわかります。メモリ内の状態は次の図で表すことができます。

その理由は、key1 の値は基本型であるため、コピー時にデータ セグメントが渡されますが、key2 の値はヒープ メモリ内のオブジェクトであるため、key2 がコピーされるときは、key2 オブジェクトを指すアドレスが渡されるからです。key2 がいくつコピーされても、その値は常に親オブジェクトの key2 オブジェクトのメモリ空間を指します。

2. ディープコピー

実際のコーディングでは、おそらく上記のような結果は望ましくありません。親オブジェクトと子オブジェクトを互いに関連付けたくありません。この場合は、ディープ コピーを使用できます。属性値の型が配列またはオブジェクトの場合にはアドレスのみが渡されるため、再帰を使用してこの問題を解決できます。親オブジェクト内のオブジェクトに属するすべての属性型を走査し、子オブジェクトに割り当てることができます。テストコードは次のとおりです。

関数Copy(p, c) {
var c = c || {};
(変数 i が p 内にある) {
p[i] の型が 'オブジェクト' の場合
              c[i] = (p[i].コンストラクタ === 配列) ? [] : {};
             コピー(p[i], c[i]);
           } それ以外 {
              c[i] = p[i];
          }
        }
c を返します。
  }    
     a.key2 = ['シャオフイ','シャオフイ'];
var b = {};
     b = コピー(a,b);        
     b.key2.push("ダフイ");
     alert(b.key2); // 小慧、小慧、大慧 alert(a.key2); // 小慧、小慧

上記から、b の key2 配列が変更されても、親オブジェクト a の key2 配列に新しい値が追加されない、つまり、子オブジェクトは親オブジェクト a の key2 に影響を与えないことがわかります。保存モードは以下のとおりです。

以上がJavaScriptスタックとコピーの詳しい説明です。JSスタックコピーの詳細については、123WORDPRESS.COMの他の関連記事にも注目してください。

以下もご興味があるかもしれません:
  • LeetCode Monotonous Stackの概要
  • 単調キューと単調スタックについての簡単な説明
  • JVM メモリ構造: プログラム カウンター、仮想マシン スタック、ローカル メソッド スタック
  • JVM スタック オーバーフローとヒープ オーバーフローの詳細な説明
  • C++ におけるモノトーン スタックの基本的なプロパティの紹介

<<:  MySQL inndbジョイントインデックスを正しく使用する方法を徹底的に理解するためのケーススタディ

>>:  nginx でクロスドメイン障害修復を構成する方法の例

推薦する

データ構造 - ツリー (III): 多方向検索ツリー B ツリー、B+ ツリー

多方向探索ツリー完全二分木の高さ: O(log2N)、ここで2は対数完全なM方向探索木の高さ: O(...

Linuxの基本コマンドmktempの詳しい説明

mptemp は安全な方法で一時ファイルまたはディレクトリを作成します。このコマンドの適用範囲: R...

vue3を使用してAppleシステムのサイドメッセージプロンプト効果を模倣する

目次アニメーションプレビューその他のUIライブラリ始めるコンポーネントディレクトリ構造トーストおおよ...

DockerにRedisをインストールし、設定ファイルとして起動する詳細な説明

更新: 最近、サーバーがマイニング ウイルスによってハッキングされたことが判明しました。これは、おそ...

Alibaba Cloud Server で MySQL デュアルマシン ホットスタンバイを手動で実装する 2 つの方法

1. コンセプト1. ホットバックアップとバックアップの違いホット バックアップは高可用性 (HA)...

DockerにNginxをインストールする方法

DockerにNginxをインストールするNginx は、IMAP/POP3/SMTP サービスも提...

メタタグコードを使用して、360 デュアルコアブラウザを互換モードではなく高速モードにデフォルト設定します。

あるウェブサイトでは、ユーザーが WebKit カーネルでページを開くことを期待して、HTML5 と...

JavaScriptは検証コードと検証のランダム生成を実装します

この記事では、検証コードのランダム生成と検証を実現するためのJavaScriptの具体的なコードを参...

40以上の美しいWebフォームデザイン例

Web フォームは、訪問者と Web サイト所有者間の主要なコミュニケーション チャネルです。フィー...

Linux bzip2 コマンドの使用

1. コマンドの紹介bzip2 は、ファイルの圧縮と解凍に使用されます。これは、Linux システム...

WeChat アプレットのカスタム下部ナビゲーション バー コンポーネント

この記事の例では、WeChatアプレットの下部ナビゲーションバーコンポーネントの具体的な実装コードを...

DockerでPython環境をパッケージ化するプロセスの詳細な説明

docker パッケージング Python 環境の手順は次のとおりです。 1 pip listの下に...

IDEA は Docker プラグインを使用します (初心者向けチュートリアル)

目次例示する1. Dockerリモートアクセスを有効にする2. Dockerに接続する3. イメージ...

CSS3 はドラッグ可能なルービックキューブの 3D 効果を実現します

主に使用される知識ポイント: •css3 3D変換 •ネイティブjsマウスドラッグイベント•表示:グ...

MySQL で大量のデータ (数千万) を素早く削除するためのいくつかの実用的なソリューションの詳細な説明

著者は最近、仕事でパフォーマンスのボトルネックの問題に遭遇しました。MySQL テーブルには毎日約 ...