2009-03-26 9 views
126

、私は単一代入して、空の状態にリセットすることができます。これは、配列が空と再利用する準備ができて、そして限り私は理解して、「シングルである「見える」を作るJavaScriptオブジェクトをすばやくクリアする方法はありますか? JavaScriptのArrayで

array.length = 0; 

オペレーション " - すなわち、一定時間。

同様の方法でJSオブジェクトをクリアすることはできますか?フィールドを繰り返して削除することができます:

しかし、これは線形の複雑さがあります。

は私もわずかの距離のオブジェクトをスローし、新しいものを作成することができます。

obj = {}; 

しかし、新しいオブジェクトの「無差別」作成がIE6のガベージコレクションで問題につながります。 (As described here

+2

"array.length == 0 ...は単一の「操作」です。つまり、一定の時間です。「私はそれを疑っています。 – Miles

+1

私はそれがコンテンツを削除するとは思わない - ちょうどpush()のようなものが配列が空であるかのように動作させる。あなたは正反対のことを言及していますか? – levik

+2

@derobert:それは少し予期しています。 IE6ガベージコレクションの問題は十分に文書化されています。 – levik

答えて

40

あなたの質問への短い答えは、私が思うには、あなたは新しいオブジェクトを作成することができます。

  1. この例では、長さを0に設定すると、すべての要素がガベージコレクションに残ります。

  2. これをObject.prototypeに追加して、頻繁に使用することができます。はい、それは複雑さは線形ですが、後でガベージコレクションをしないものはすべてです。

  3. これが最適なソリューションです。私はそれがあなたの質問に関連していないことを知っています - しかし、私たちはIE6を何度もサポートする必要がありますか?その使用を中止するキャンペーンがたくさんあります。

上記の内容が間違っている場合は、私に修正してください。

+4

ポリシーの問題としてIE6をサポートし、それは2桁の市場シェアを享受する。 IE GCの問題は、収集されていないものではなく、コレクションがすべてのX割り当てを実行し、毎回時間がかかることです。したがって、オブジェクトを再利用する必要があります。 – levik

+0

ええ、会社の方針などでまだ使用されているケースは多いです。私は偽りなくトピックのランキングを外していました:) どのように削除obj.prop;そのプロパティ自体がオブジェクトであるときに実行しますか?私はあなたがそこで効率を上げるかどうか分かりません。 – jthompson

+2

GCが悪いということは、IE6が遅く実行されることを意味します。つまり、アップグレードするインセンティブがさらに増えます。あなたはまだそれをサポートしている、それは遅く実行されるだけです。 – nickf

5

あなたの質問を要約すると、できるだけIE6 GCのバグに悩まされたくありません。そのバグは、2つの原因があります。

  1. ガベージコレクションが1回発生するごとに非常に多くの配分。したがって、より多くの割り当てを行うと、oftener GCが実行されます。
  2. 「空中」になっているオブジェクトが増えるほど、ガベージコレクションの実行に多くの時間がかかります(ゴミとしてマークされているオブジェクトのリスト全体をクロールするため)。

1の原因となる解決策は、割り当ての数を減らすことです。可能な限り新しいオブジェクトと文字列を割り当てます。

2を引き起こす解決策は、「ライブ」オブジェクトの数を減らすことです。不要になったらすぐに文字列やオブジェクトを削除し、必要に応じて新しい文字列やオブジェクトを作成してください。

ある程度、これらの解決策は矛盾しています。つまり、メモリ内のオブジェクトの数を少なくすると、より多くの割り当てと割り当て解除が行われます。逆に、同じオブジェクトを常に再利用するということは、厳密に必要なものより多くのオブジェクトをメモリに保持することを意味する可能性があります。


ここでご質問ください。新しいオブジェクトを作成することでオブジェクトをリセットするか、すべてのプロパティを削除するかによって、オブジェクトは後で処理したいオブジェクトに依存します。

は、おそらくそこに新しいプロパティを割り当てることになるでしょう:

  • あなたはそうすぐに、私は削除するか、最初にクリアする新しいプロパティ、すぐに割り当て、スキップすることをお勧めします場合。ただし、のすべてのプロパティが上書きまたは削除されていることを確認してください!)
  • オブジェクトがすぐには使用されず、後で再投入される場合は、削除するか、後で新しいものを作成する。

JScriptオブジェクトを新しいオブジェクトであるかのように再利用するために、JScriptオブジェクトをクリアする方法はありません。つまり、あなたの質問への短い答えは「いいえ」です、つまりjthompsonが言うように。

82

まあ、物事があまりにも簡単に行うことのリスクが...

for (var member in myObject) delete myObject[member]; 

は...怖いブラケットを最小限に抑えて1行のコードでオブジェクトを洗浄するのにはかなり有効であると思われます。すべてのメンバーは、ゴミとして放置されずに真に削除されます。

もちろん、オブジェクト自体を削除したい場合は、そのために別途delete()を実行する必要があります。

+0

削除すると、参照のみが破損します。 myObject [メンバ]は未定義に評価され、オブジェクトへの別の参照が存在しない限り、技術的にオブジェクトはガベージとして残ります。 –

+0

この回答は非常に責任があります。ディスフェースフェーズのすべての管理対象オブジェクトに適用されると、一般に、偶発的なオブジェクトチェーンの多くが処理されます。 Rock on Wytze – deepelement

+1

OPは、このループで 'hasOwnProperty'を使うことを提案しています。私はドキュメントを読んだが、 'hasOwnProperty()'チェックを省略すると、もしあれば何が危険なのかについて私の頭を払うつもりだ。 – logidelic

0

小道具を削除することはできますが、変数は削除しないでください。 delete abc;はES5では無効です(use strictを指定してスローします)。

あなたはオブジェクトのlengthプロパティを設定

は何も変わりません(それはあなたがプロパティへの他の参照を持っていない場合)GCへの削除のためにそれを設定することがnullに割り当てることができます。

+0

配列の 'length'を0に設定すると(オブジェクトの特定の型です - あなたが私を信じていない場合、' typeof [] 'を実行してみてください)、プロパティを設定するだけでなく、実際には配列の内容はクリアされます。 http://stackoverflow.com/questions/1232040/how-do-i-empty-an-array-in-javascript#comment7533900_1234337 –

3

ES7のObject.observeと一般的なデータバインディングを楽しみにしていて、何か新しいことを考えてみましょう。次のように考えてください:

var foo={ 
    name: "hello" 
}; 

Object.observe(foo, function(){alert('modified');}); // bind to foo 

foo={}; // You are no longer bound to foo but to an orphaned version of it 
foo.name="there"; // This change will be missed by Object.observe() 

したがって、この状況では#2が最適な選択です。

+0

オブジェクトをビューにバインドすることができるAngularJSなどのフレームワークを使用している場合(片方向または双方向のバインディング) 'obj = {}'でオブジェクトを消去すると、フレームワークはオブジェクトへのそれ以上の変更を認識しないので、テンプレートは適切にレンダリングされません。しかし、オプション2は適切に機能します。 –

+0

良い点。同じヒープオブジェクトを保持する必要があります。これは、同じ参照を保持したいと考える別の理由を示しています。 – Cody

-3

は単純に実行します。

myObject = {}; 

これはそれの値のオブジェクトがクリアされます。

+14

これは、オブジェクトへの参照をすべて破棄します。 – weltschmerz

+10

dchackeのコメントを明確にする:\t 'myObject = {}'は新しいオブジェクトを作成し、元のオブジェクトをそのまま残します。これは、元のオブジェクトへの他の参照がある場合に違いがあります: 'var myObject = {a:5、b:4}; var otherRef = myObject; myObject = {}; '最後に' otherRef'は期待通りに '{a:5、b4}'と** '** {{}'ではありません。 – Ignitor

3

これを試すことができます。以下の関数は、オブジェクトのプロパティのすべての値をundefinedに設定します。ネストされたオブジェクトと同様に機能します。

var clearObjectValues = (objToClear) => { 
    Object.keys(objToClear).forEach((param) => { 
     if ((objToClear[param]).toString() === "[object Object]") { 
      clearObjectValues(objToClear[param]); 
     } else { 
      objToClear[param] = undefined; 
     } 
    }) 
    return objToClear; 
}; 
14

ES5

ES5ソリューションをすることができます:

// for enumerable properties 
Object.keys(obj).forEach(function (prop) { 
    delete obj[prop]; 
}); 

// for all properties 
Object.getOwnPropertyNames(obj).forEach(function (prop) { 
    delete obj[prop]; 
}); 

ES6

そしてES6ソリューションをすることができます:

// for enumerable properties 
for (const prop of Object.keys(obj)) { 
    delete obj[prop]; 
} 

// for all properties 
for (const prop of Object.getOwnPropertyNames(obj)) { 
    delete obj[prop]; 
} 

パフォーマンス

かかわらず、スペックの、最速のソリューションは、一般的に次のようになります。

// for enumerable properties 
var props = Object.keys(obj); 
for (var i = 0; i < props.length; i++) { 
    delete obj[props[i]]; 
} 

// for all properties of an object with proto chain 
var props = Object.getOwnPropertyNames(obj); 
for (var i = 0; i < props.length; i++) { 
    delete obj[props[i]]; 
} 

// for all properties of shallow/plain object 
for (var key in obj) { 
    // this check can be safely omitted in modern JS engines 
    // if (obj.hasOwnProperty(key)) 
    delete obj[key]; 
} 

for..inだけ浅いまたはプレーンオブジェクトで実行されなければならない理由は、それがprototypically継承されるプロパティを横断するあるだけではなく、独自のプロパティそれは削除することができます。オブジェクトが明白でないことが分かっていない場合は、forObject.getOwnPropertyNamesを使用することをお勧めします。

関連する問題