4

次のことを(グローバルスコープで)行うと:

var myObject = {name: "Bob"};

メモリ内のそのオブジェクト (つまり、文字列識別子 "myObject)" を指す方法があります。コンソールを開いて次のように入力myObject.nameすると、コンソールは次のように応答します。

"Bob"

ここで、次のように入力すると:

{name: "Jane"};

私はそのオブジェクトをどこかに作成していますが、それは何らかの範囲で生き続けると推測しています。見つける方法はありますか?windowジェネリックストアのどこかに存在しますか?

編集:一部の人々は、ガベージコレクションが行われるだけだと言っています。

では、次の例はどうでしょうか。

var MyObject = function(){
    $("button").click(this.alert);
}

MyObject.prototype.alert = function(){
    alert("I heard that!")
}

new MyObject();

コールバックが DOM イベントにバインドされているため、ガベージ コレクションを実行できません。結果のオブジェクトはどこにあり、アクセスできますか?

4

2 に答える 2

5

このオブジェクトを指す参照がない場合 (つまり、変数またはプロパティの値に割り当てていない場合)、それにアクセスする方法はなく、実際には、ガベージ コレクターが再利用できるため、生きていません。すぐにこの記憶。

于 2013-06-28T13:52:43.910 に答える
2

短い答えはノーです。オブジェクトは、到達できない場所のメモリ内で生き続けません。ビットライフは生きています: 真実はもう少し複雑ですが、基本を理解していればそれほどではありません.

更新:
あなたの更新に応じて: ある意味で、あなたは正しいです。コールバックは への参照でMyObject.prototype.alertあり、 を使用してアクセスしthis.alertましたが、その関数オブジェクトはコンストラクター プロトタイプによって参照されており、とにかく GC できません。インスタンス自体は関数自体に関与していないalertため、安全に GC できます。

次のように考えてください。

MyConstructor.prototype.alert = 0x000123;//some memory address
   ||
   \/
0x000123 = [object Function];

関数オブジェクト自体は何にも直接アタッチされておらず、メモリ内に浮かんでいて、プロトタイプによって参照されています。インスタンスを作成する場合:

new MyConstructor().alert;

次のように解決されます。

[new MyConstructor instance] allocated at e.g 0x000321
   ||
   \\
    \=>[alert] check for alert @instance -> not found
          \\
           \=> check prototype, yield 0x000123 <-- memory address, return this value

したがって、ステートメントを実行すると:

 $("button").click(this.alert);

this.alertに解決される式です0x000123。つまり、jQ のclickメソッド (関数オブジェクト) は、関数オブジェクトのメモリ アドレスのみを受け取りalertます。インスタンス、または実際にはコンストラクターはまったく関与していません。そのためthis、 、または呼び出しコンテキストは、関数が呼び出される方法と場所に応じて変化する可能性があります。アドホック コンテキストの決定の詳細については、こちらを参照してください

私はあなたにもっと良いことをします:

/*assume your code is here*/
new MyConstructor().alert = function(){ alert('I am deaf');};
MyConstructor.prototype.alert = 'foo';
$('#button').click();

何を推測すると、クリック イベント アラート「私はそれを聞いた」とまったく同じで、インスタンスは言うまでもなく、プロトタイプも関与していません。スコープ外に出た
場合でも、GC はまだスコープ外になっていないアラート関数オブジェクトへの参照を参照しているため、イベントは正常に機能します。ただし、他のすべてはGCで利用できます...MyConstructorclick


JS ガベージ コレクター (GC) は、フラグ アンド スワイプ GC です。JS エンジンがステートメントを検出すると、オブジェクトを格納するために必要なメモリを割り当てます。次のステートメントに到達したとき、そのオブジェクトはおそらくまだメモリ内にあります。
時々、GC はメモリ内にあるすべてのオブジェクトを X チェックし、まだアクセス可能なオブジェクトへのすべての参照を見つけようとします。そのステートメントで作成されたばかりで参照が割り当てられていないオブジェクト リテラルに遭遇すると、そのオブジェクトにはガベージ コレクションのフラグが立てられます。
次に GC がフラグ付きオブジェクトをスワイプする処理に取り掛かると、そのオブジェクトはメモリから削除されます。

もちろん、これはすべてのエンジンに完全に当てはまるわけではありません。関数を返す IIFE でステートメントが記述されているとします。

var foo = function()
{
    {name: 'bar'};
    return function()
    {
        return 'foobar';
    };
}());

一部のエンジンは、IIFE のスコープ全体をメモリに保持し、IIFE の戻り値がスコープ外になった (GC のフラグが立てられた) 場合にのみ、そのスコープのメモリの割り当てを解除します。前回チェックしたV8のような他のエンジンは、実際には、戻り値によって参照されていない外側のスコープのオブジェクト/変数にフラグを立てます。
ただし、考えてみると、IIFE が戻る前に GC が開始される可能性があるため、このケースには当てはまらない可能性があります。

考慮すべき論理 OR の問題もあります。

var name = (mayNotExist || {name:'default'}).name;

この場合、mayNotExist 存在する場合、 JS の式の短絡評価のおかげで、オブジェクト リテラルは作成されません。

問題に関するいくつかのリンク:

于 2013-06-28T13:57:19.793 に答える