JavaScriptでのオブジェクトの削除


359

私はJavaScriptのdelete演算子と少し混乱しています。次のコードを見てください。

var obj = {
    helloText: "Hello World!"
};

var foo = obj;

delete obj;

このコードが実行された後、objisですがnullfooそれでもとまったく同じようにオブジェクトを参照しますobj。このオブジェクトは、foo指し示したオブジェクトと同じだと思います。

これは私を混乱させます。なぜなら、書き込みdelete objobjは、変数だけでなく、メモリ内を指しているオブジェクトも削除されると思っていたからですobj

JavaScriptののガベージコレクタは、私がオブジェクトを指し、他の変数を持っていなかった場合は、それがそうすることを、保持/解放的に取り組んでいるためですでしょうメモリから削除されますか?

(ちなみに、私のテストはSafari 4で行われました。)



DELETEキーワードで記事本文webcache.googleusercontent.com/...
Vitim.us

2
上記のリンクは次のようになります:perfectionkills.com/understanding-delete
johnmdonahue 2013年

1
@Steveハリソン削除は、あなたのケースの中にオブジェクトキー削除のためのJavaScriptの削除使用中のオブジェクトを削除するためではありませんvar obj = { helloText: "Hello World!" }; var foo = obj; delete obj;チェックオブジェクトが削除されていませんobj:削除、使用delete obj.helloTextして、チェックfoo now foo is an empty object
Umairアーメド

2
@UmairAhmed、無料翻訳: "" " deleteはJavaScriptでオブジェクトを削除するためのものではありません。deleteオブジェクトキーを削除するために使用されます。この場合var obj = { helloText: "Hello World!" }; var foo = obj; delete obj;、オブジェクトは削除されません。チェックしてくださいobj。次に実行するdelete obj.helloTextfoo、空をポイントしていることがわかりますオブジェクト "" "
パチェリエ2017年

回答:


448

削除演算子は参照のみを削除し、オブジェクト自体は削除しません。オブジェクト自体を削除した場合、他の残りの参照は、C ++の削除のようにぶら下がります。(そして、それらの1つにアクセスすると、クラッシュが発生します。それらすべてをnullにするには、削除時に追加の作業を行うか、各オブジェクトのメモリを追加する必要があります。)

JavaScriptはガベージコレクションされているため、オブジェクト自体を削除する必要はありません。オブジェクトを参照する方法がなくなった場合、オブジェクトは削除されます。

オブジェクトへの参照を使い終わったら、それを削除すると便利です。これにより、ガベージコレクターは、何を再利用できるかについてのより多くの情報が得られるからです。ラージオブジェクトへの参照が残っている場合、プログラムの残りの部分が実際にそのオブジェクトを使用していなくても、これによりオブジェクトが解放されないことがあります。


23
deleteキーワードは、オブジェクトのプロパティではなく、変数のために働きます。perfectionkills.com/understanding-delete
Alex Mund

1
@AlexJMはい、Guffa(およびそのコメント)からの次の回答では、これについて少し詳しく説明しています。
Jesse Rusak

1
オブジェクトのプロパティは別のオブジェクトにすることができます。例えば; var obj = {a: {}}; delete obj.a;
Alex Mund

2
しかし...変数は実際にはのプロパティではありませんwindowか?
RedClover

3
ローカル変数ではなく@Soaku。(例:で宣言されたものvar
Jesse Rusak

162

このdeleteコマンドは通常の変数には影響せず、プロパティにのみ影響します。deleteコマンドの後、プロパティには値nullがありませんが、それはまったく存在しません。

プロパティがオブジェクト参照の場合、deleteコマンドはプロパティを削除しますが、オブジェクトは削除しません。ガベージコレクターは、他の参照がない場合にオブジェクトを処理します。

例:

var x = new Object();
x.y = 42;

alert(x.y); // shows '42'

delete x; // no effect
alert(x.y); // still shows '42'

delete x.y; // deletes the property
alert(x.y); // shows 'undefined'

(Firefoxでテスト済み。)


39
これがグローバルスコープで実行される場合、x変数はグローバルwindowオブジェクトの単なるプロパティになり、delete x;実際にはx変数が完全に削除されます。
クレセントフレッシュ

18
@crescentfresh:暗黙的に宣言されている場合のみプロパティになります。例のように明示的に宣言されている場合、それはグローバル変数であり、削除できません。
グッファ、2009

4
@Tarynn:なるほど、そこに問題があります。コンソールでこれを行うと、何らかの理由でxで一部のブラウザでは適切な変数にならず、windowオブジェクトのプロパティになります。これはもちろんコンソールの問題であり、コードが通常実行される方法を反映していません。
Guffa

2
@Guffaたくさんの調査の後、私はそれを認めざるを得ませんでした。反対票を投じるのに十分な担当者がいなかったのはおそらく良いことでした。心からお詫び申し上げます。時間を割いて、何が起こっているのかを示してくれてありがとう...ここに詳細な説明があります:perfectionkills.com/understanding-delete/#firebug_confusion
Tarynn

2
@chao:なるほど。Tarynnと同じ問題が発生しています(以前のコメントを参照)。コンソールでこれを行うと、実際のコードと同じように機能しません。
Guffa 2013

56

「暗黙的に宣言された変数」はグローバルオブジェクトのプロパティであるため、deleteは他のプロパティと同様に機能します。varで宣言された変数は破壊できません。


53
私はvarがそれほど悪いものであることに気づかなかった。
Gavin、2014年

1
これは素晴らしい点であり、JSの落とし穴です。人々はウィンドウ変数を削除することに慣れていて、なぜローカル変数で同じことができないのか疑問に思っています。
welbornio 2015年

2
同じことが当てはまりますlet
パセリエ2017年


4

delete JavaScriptのオブジェクトの削除には使用されません。

deleteobject keyあなたのケースで削除するために使用

var obj = { helloText: "Hello World!" }; 
var foo = obj;
delete obj;

オブジェクトは削除されていません。チェックobjは同じ値を 使用しています。

delete obj.helloText

次に、をチェックしobj, fooます。どちらも空のオブジェクトです。


2

この問題に照らして興味深いと思われるjsperfを見つけました。(写真を完成させるために手元に置いておくと便利です)

削除ヌルの設定、未定義の設定を比較します

ただし、プロパティを何度も削除または設定した場合のケースをテストすることに注意してください。



1

IE 5から8には、ホストオブジェクト(ウィンドウ、グローバル、DOMなど)のプロパティで削除を使用するとTypeError「オブジェクトがこのアクションをサポートしない」をスローするバグがあります。

var el=document.getElementById("anElementId");
el.foo = {bar:"baz"};
try{
    delete el.foo;
}catch(){
    //alert("Curses, drats and double double damn!");
    el.foo=undefined; // a work around
}

後で IEで常にtrueが返されるel.foo !== undefinedため、プロパティが完全な値を使用する意味があるかどうかを確認する必要がある場合"foo" in el

プロパティが本当に消える必要がある場合...

function hostProxy(host){
    if(host===null || host===undefined) return host;
    if(!"_hostProxy" in host){
       host._hostproxy={_host:host,prototype:host};
    }
    return host._hostproxy;
}
var el=hostProxy(document.getElementById("anElementId"));
el.foo = {bar:"baz"};

delete el.foo; // removing property if a non-host object

ホストAPIでホストオブジェクトを使用する必要がある場合...

el.parent.removeChild(el._host);

1

私はこの同じ答えを探してこの記事を偶然見つけました。私がやったことはobj.pop()、オブジェクトに格納されているすべての値/オブジェクトをポップアウトして、オブジェクトを再利用できるようにすることです。これが悪い習慣かどうかはわかりません。この手法は、Chrome DevツールまたはFireFox Webコンソールでコードをテストするのに役立ちました。


1

これは私にとっては効果的ですが、良い方法ではありません。オブジェクトが関連付けられている関連要素をすべて削除するだけです。

 for (element in homeService) {
          delete homeService[element];
  }

ベストプラクティスは何ですか?削除演算子はオブジェクトのプロパティを削除するのに最適ではなかったと読んだことを覚えています。私はこれをCrockfordのJavaScriptブックで読んだと思いますが、現時点では掘り下げることができません。
zero_cool

0

変数を設定するnullと、DOM要素とJavaScriptスコープ間で行われる循環参照を含め、すべてのブラウザーでオブジェクトへの参照が確実に解除されます。deleteコマンドを使用して、ガベージコレクションの次回の実行時にクリアするオブジェクトをマークしていますが、同じオブジェクトを参照する変数が複数ある場合、単一の変数を削除してもオブジェクトは解放されず、その変数とオブジェクト。そして、ガベージコレクションの次の実行では、変数のみがクリーンアップされます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.