2012-01-20 15 views
49

削除オペレータの動作はvery complicated and there are many misunderstandings about what it actually doesと思われます。私には、undefinedに何かを再割り当てすると、あなたが期待していたことをより確実にするようです。Javascriptでの削除演算子の目的は何ですか?

Javascriptのdeleteキーワードは、実際には非サンプルコードで使用されていることはありませんでした。何かに役立つかどうかは疑問です。 には、undefinedへの再割り当てによって達成できない目的がありますか?有名なライブラリ(例:jQuery、dojo、backboneなど)で全く使用されていますか?

+0

'delete'の動作は全く複雑ではありません。しかし** **本当に**は削除と呼ばれるべきではありません。 JavaScriptはC++と構文的に似ていますが、演算子C++を使用していますが、これとはまったく異なる*を実行することはちょっとのおしゃれであり、この混乱の原因となっています。 (もしそれが 'remove'と呼ばれていたら、私は人々がほとんど混乱しないだろうと確信している) –

+0

http://perfectionkills.com/understanding-delete/ – Raghu

答えて

61

削除には未定義に再割り当てすることで達成できない目的がありますか?

はい。プロトタイプからプロパティのマスクを解除するか、inhasOwnProperty、およびfor (...in...)にプロパティが存在しないと記録する場合は、deleteが適切です。

var set = {}; 

set._x = true; 

alert('_x' in set); // true 

set._x = undefined; 

alert('_x' in set); // true 

delete set._x; 

alert('_x' in set); // false 

EDIT:As T.J.クラウダーは説明:

deleteオペレータの目的は、単にundefinedにプロパティを設定undefinedにプロパティを設定する一方、完全に、オブジェクトからプロパティを除去することです。

これは、それ自体では重要、しかし、あなたは、継承を使用しているとき、OはPから派生した場合ので、それはまた、重要

var P = { prop: 42 }; 
var O = Object.create(P); // P is O's prototype. 

あなたがO.propを取得するとき、あなたは小道具の値を取得Oがその名前のプロパティを持っている場合(その値が未定義であっても)、Oがプロパティをまったく持たない場合、代わりにP.propから値が取得されます。

alert(O.prop); // "42" since O doesn't have its own prop, but P does. 
O.prop = undefined; 
alert(O.prop); // "undefined" since O has its own prop. 
delete O.prop; 
alert(O.prop); // "42" since the delete "unmasked" P.prop. 
0

さて、あなたのオブジェクトには、値undefinedを含む要素があります。キーはなくなっていないだろう。

9

あなたは

delete Foo.Bar; 

をすれば、それは完全に

オブジェクトはFooからプロパティバー
Foo.Bar = undefined 

は単に未定義にバーのプロパティを設定し、Foo.Barはまだ

1

あなたが存在して削除しますの答えを確認することができます次のリンクCan I set variables to undefined or pass undefined as an argument?の違いを非常に詳細に説明しています。

概要:

あなたは確かにそれに未定義割り当てることができますが、それは 変数は削除されません。 delete object.property演算子のみが実際に ものを削除します。

削除は実際には変数ではなくプロパティのためのものです。 ブラウザでは、まっすぐに変数を削除することができますが、それは ではないので、ECMAScript Fifth Editionのstrict モードでは機能しません。 ガベージコレクションを行うことができるように、何かへの参照を解放したい場合は、variable = nullと言うのが普通です。

19

マイクサミュエル氏は答えて指摘しているように、削除の最も一般的な使い方の1つは、名前を値に関連付ける「プロパティバッグ」としてオブジェクトを扱うときです。論理的には、「この名前は現在、いくつかの偽の値にマップされている」と「この名前は全くマッピングされていません」との間に違いがあります。 "削除"は後者を達成する。

それはすべてかなり合理的に理解されています。私は、JScript 1.0から5.0のエンジンに関する興味深い履歴ノートを追加すると思っていました。

MicrosoftのJScript実装では、OLEオートメーションスタイルのIDispatchオブジェクトを使用して、拡張オブジェクトを実装しました。 IDispatchはもちろん、名前を「ディスパッチid」(単純に整数)に関連付けることによって動作します。動的に呼び出すには、まず、ディスパッチオブジェクトに名前に関連付けられたディスパッチIDを渡すように依頼し、次に「これらの引数を指定して、このIDに関連付けられたメソッドを呼び出す」と言う。

これはすべてうまくいいです。しかし、IDispatch契約の要件の1つは、名前からディスパッチIDへのマッピングがオブジェクトの全寿命にわたって安定するであることです。だから、もし誰かが "このオブジェクトにFooプロパティを追加する"と言うと、プロパティFooがそのオブジェクトのディスパッチ識別子0x1234に関連付けられていると判断するかもしれません。その時刻から、毎回のオブジェクトはディスパッチ識別子 "Foo"を要求されますが、Fooが削除されてから再び追加されても0x1234、を返す必要があります。これにより、呼び出し側は常に呼び出しごとにオブジェクトに尋ねるのではなく、名前/設定のペアの高速キャッシュを維持することができます。

実用的なことは、です。「削除」は、その実装におけるオブジェクトのメモリ負担を少しでも軽減します。!オリジナルの実装でプロパティを削除するときは、そのディスパッチ識別子を削除済みとしてマークするオブジェクトにビットを追加する必要がありますが、その名前が戻った場合の名前/ IDのペアリングに関する情報をすべて保持する必要があります。膨大な数のプロパティをオブジェクトに追加し、それらのすべてを削除しても、メモリ内のオブジェクトは縮小されません。

JScriptエンジンは私の時間(パーサーとレクサーを除く)から完全に書き直されているので、エンジンにまだこのような奇妙なことがあるかどうかはわかりません。見つけ出すのは面白いだろう。

2

その他の回答はdeleteキーワードの背後にある動機を説明しています。私は2017年の時点で、ブラウザは、プロパティを削除するときとプロパティを未定義に設定するときの両方で、メモリの割り当てを解除するとします。

この例(source of roughSizeOfObject())を考える:

> var obj = {a:42,b:"b"}; roughSizeOfObject(obj) 
26 
> obj.a = undefined; roughSizeOfObject(obj) 
18 
> delete obj.a; roughSizeOfObject(obj) 
10 
> obj.b = undefined; roughSizeOfObject(obj) 
8 
> delete obj.b; roughSizeOfObject(obj) 
0 

例(Stringのすべての文字は、内部16ビットの符号なし整数として符号化されていることに注意)、クロム61(64ビット)のコンソールから来ます。

関連する問題