5

何かツリー構造を作成しようとしています。

次のように自分のデータにアクセスしたいと思います。

data[key1][key2]

ただし、key1とkey2には対称的な関係があります。次のことが常に当てはまります。

data[key1][key2] == data[key2][key1]

より具体的には、一方への変更が他方に影響を与えるように、同じオブジェクトを持っdata[key1][key2]てポイントしています。data[key2][key1]

基になるオブジェクトを削除したいので、問題が発生します。私が使用するかどうか知っています:

delete data[key1][key2];

data[key2][key1]まだオブジェクトを参照しています。

私の質問はこれです:上記の両方のプロパティがfalseを評価するように、基になるオブジェクトを削除したり、falseを上書きしたりする方法はありますか?

4

3 に答える 3

3

このように考えてください:

data[key1][key2] -----> object1
                          ^
data[key2][key1] ---------+

それらの1つ(後者など)のキーを新しいオブジェクトに変更すると、次のようになります。

data[key1][key2] -----> object1

data[key2][key1] -----------> object2

(または、キーを削除すると、キーが失われるだけです:)

data[key1][key2] -----> object1

data[key2]

つまり、参照の1つは変更しますが、もう1つは変更しません。それらの1つだけを交換しようとすると、これが達成されます。2つのオプションがあります。

a)新しいオブジェクトを指すように両方のキーを変更します。

data[key1][key2] -----> object2
                          ^
data[key2][key1] ---------+

(または両方のキーを削除します:)

data[key1][key2]       object1 (no references, will be garbage collected)

data[key2][key1]

b)オブジェクト自体のフィールドを変更します。このように、両方とも同じオブジェクトを指していることになりますが、それに関する何かが異なります。ただし、使用するコードでは、これを考慮に入れる必要があります。

data[key1][key2] -----> object1 with 'isDeleted'=true
                          ^
data[key2][key1] ---------+

a)オプションは、ユースケースを考えると最も理にかなっているようです。とにかく両方のキーを持っている場合は、両方を更新/削除してみませんか?

于 2012-09-25T22:52:34.920 に答える
1

あなたはおそらく他の答えからあなたが必要とするものを持っていますが、要約すると:

私の質問はこれです:基礎となるオブジェクトを削除する方法はありますか

いいえ。それへのすべての参照を削除して、ガベージコレクションに使用できるようにすることができます。ガベージコレクターが実行されると(不特定の時間に)、オブジェクトが削除されます。

または、上記の両方のプロパティがfalseを評価するように、falseを何かで上書きしますか?

ではない正確に。各プロパティに新しい値を割り当てることができるのは、それらがfalse(false、null、undefined、0など)と評価されるようにするためです。オブジェクトはそれらを参照する識別子を追跡しないため、「このオブジェクトへのすべての参照を削除する」と言う一般的な方法はありません。それを実行したい場合は、参照を追跡し、それらの値を自分で変更する必要があります。

別の方法は、オブジェクトに、他のプロパティにアクセスするときにチェックできる、使用する必要があるかどうかを示すプロパティ(「廃止」など)を与えることです。パブリックプロパティは非常に単純です。または、コンストラクターでクロージャーを使用して「プライベート」メンバーを作成できます。

function Foo() {
  var obsolete = false;

  this.obsolete = function (){
    return obsolete;
  };

  this.delete = function (){
    obsolete = true;
  };
}

var foo = new Foo();
var bar = new Foo();

alert(foo.obsolete() + ', ' + bar.obsolete()); // false, false

foo.delete();

alert(foo.obsolete() + ', ' + bar.obsolete()); // true, false

それはあなたが望むのとほとんど同じように機能します。オブジェクトを削除できる場合は、次のことを行う必要があります。

if ( data[key1][key2] ) {
  // do stuff
}

上記の方法を使用すると、次のようになります。

if ( !data[key1][key2].obsolete() ) {
  // do stuff
}

オブジェクトがまだ実際に存在していることに注意してください。廃止現在に変更し、ブール値を逆にして、if (obj.current())ではなくチェックすることをお勧めしますif (!obj.obsolete())。合うものは何でも。

于 2012-09-25T23:54:57.577 に答える
1

valueOf()メソッドが解決策を提供する場合があります。ブール値と明示的に比較している場合、valueOfはブールへの型キャストの一部として呼び出されます。たとえば、データ構造がオブジェクトを参照しているとしましょうx...

> x = {}
Object
> (x == false ? 'yes' : 'no')
"no"
> x.valueOf = function() {return false;}
function () {return false;}
> (x == false ? 'yes' : 'no')
"yes"

...つまり、の場合data[key1][key2] == data[key2][key1] == x、割り当てると、ブール値に明示的にカーストされたときの評価x.valueOf = function() {return false;}が変更されます。をテストしている限り、は偽物のように見えるはずです。xdata[key1][key2] == falsex

xただし、これはプリミティブ値よりも偽造が少ないため、注意する必要があります。たとえば、上記のようにvalueOfを割り当てた後でも、暗黙の強制は依然として真実であるように見えます...

(x ? 'yes' : 'no')
"yes"
于 2012-09-25T23:25:52.217 に答える