1

オブジェクト (配列など) を代入するときの代入演算子がわかりません。代入演算子として参照をコピーすると言われています。ただし、データをコピーしているようです。例えば:

var globArray = [];

function test() {
  var names = ["craig", "silva"];
  globArray = names;
}//endFunction test

function test2() {
  console.log("el1: ", globArray[0], "el2: ", globArray[1]);
}//endFunction test2

TEST を呼び出すと、配列 NAMES が作成され、グローバル配列「globArray」が NAMES に割り当てられます。今は範囲外なので、「名前」はなくなりましたよね?その後、test2 を呼び出しますが、要素が表示されます。したがって、単に参照をコピーするのではなく、オブジェクト全体をコピーする必要があります。

誰かがこれを説明できますか?

4

5 に答える 5

6

「テスト」関数が戻ったとき、「名前」が「なくなった」ことは正しいです。ただし、グローバル変数に割り当てられているため、その値はそうではありません。「names」ローカル変数のは、配列オブジェクトへの参照でした。その参照はグローバル変数にコピーされたため、グローバル変数にも配列オブジェクトへの参照が含まれるようになりました。

オブジェクトの割り当てはグローバルなものです。オブジェクトが割り当てられ、ローカル変数によって参照されると、オブジェクトへの他の参照 (直接的または間接的) が存在しない限り、スコープが非アクティブになるときにローカル変数が消えると、ガベージ コレクションが行われます。直接参照はあなたのようなケースです。ローカルスコープがローカル変数への参照を含む関数を「リーク」すると、間接参照が発生する可能性があります。

于 2012-10-24T13:30:32.750 に答える
3

ここでは、アクティベーション レコードとヒープ上のオブジェクトの 2 つが関係しています。

グローバル変数のアクティベーション フレームから始めます。

globArray : undefined

ヒープには、コードに表示されるリテラルが含まれています

ptr0      : "craig"
ptr1      : "silva"

、などはptr0ptr1メモリ内の特定の場所を参照する単なるアドレスまたはラベルです。

を呼び出すtest()と、インタープリターは、ローカル変数用のボックスを含む新しいアクティベーション フレームをプッシュします。

globArray : undefined
---------------------
names     : undefined

次に、インタープリターは["craig", "silva"]、ヒープ上にオブジェクトを作成するものを評価します。

ptr0      : "craig"
ptr1      : "silva"
ptr2      : [ &ptr0, &ptr1 ]

これptr2は、2 つの値を指す配列を含むメモリ内の場所です。

このメモリの場所はnames、アクティベーション レコード内の場所に格納されるようになったため、コール スタックは次のようになります。

globArray : undefined
---------------------
names     : &ptr2

割り当てnames = ...はヒープを変更せず、アクティベーション レコードのみを変更します。

次にglobArray = names、1 つのアクティベーション レコード エントリの内容を別のエントリにコピーします。

globArray : &ptr2
---------------------
names     : &ptr2

その後、 への呼び出しがtest終了し、アクティベーション レコードが破棄されます。

globArray : &ptr2

ここで、global はglobArrayへの呼び出し中に作成されたオブジェクトを指しますtest。関数の最後は、ヒープではなく、アクティブなアクティベーション レコードを変更するだけなので、ヒープは次のようになります。

ptr0      : "craig"
ptr1      : "silva"
ptr2      : [ &ptr0, &ptr1 ]

ptr2同じ配列のままです。

「名前」がなくなったのですね。

names(アクティベーション レコードのエントリ) はなくなりましたが、アクティブなアクティベーション レコードのエントリによってまだポイントされているため、それが指していたオブジェクトはありませんglobArray

その後、test2 を呼び出しますが、要素が表示されます。したがって、オブジェクト全体をコピーする必要があります

いいえ、そのオブジェクトが占有するヒープ内の場所への参照をコピーしただけです。ヒープが変更されていないため、新しいオブジェクトは作成されず、ヒープはすべてのオブジェクトが作成される場所です。

スタックとヒープとは何ですか? 興味があるかもしれません。

于 2012-10-24T13:38:29.837 に答える
2

Javascript オブジェクトはガベージ コレクションされます。

変数によって参照されるオブジェクトは、グローバル変数によって引き続き参照されるため、終了names後も存在し続けます。test()

于 2012-10-24T13:31:12.080 に答える
2

名前と globalArray はどちらも同じオブジェクトを参照しています。このオブジェクトへの参照がスコープ内に少なくとも 1 つある限り、このオブジェクトは「消える」ことはありません。何がなくなったか知っていますか?参照される初期配列 globalArray。

于 2012-10-24T13:32:08.317 に答える
0

オブジェクトは、それへの参照を保持する変数から分離されています。変数がなくなった後でも、オブジェクトはまだ存在している可能性があります。これがコードで起こっていることです。names変数がなくなった場合でも、変数が参照していたオブジェクトは変数とは無関係にまだ存在していますname。オブジェクトへの参照が残っていない場合にのみ、メモリから削除されます。

オブジェクトを割り当てるときに、データがコピーされていないことを確認できます。オブジェクトを別の変数に割り当てた後、最初の変数を使用してオブジェクトを変更できます。他の変数を使用すると、オブジェクトが変更されます。

function test() {
  var names = ["craig", "silva"];
  globArray = names;
  names[0] = 'peter';
}

の内容を表示すると、globArrayとが表示されます。これは、両方の変数が同じ配列オブジェクトへの参照を持っているためです。petersilva

于 2012-10-24T13:39:25.757 に答える