我正在尝试创建一些树形结构。
我希望按如下方式访问我的数据:
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?
答案 0 :(得分:3)
这样想:
data[key1][key2] -----> object1
^
data[key2][key1] ---------+
如果你将其中一个(比如说后者)的密钥更改为新对象,你就会得到这个:
data[key1][key2] -----> object1
data[key2][key1] -----------> object2
(或者,如果删除它,密钥将会丢失:)
data[key1][key2] -----> object1
data[key2]
也就是说,您将更改其中一个引用但不更改另一个引用。任何只替换其中一个的尝试都可以实现这一目标。您有两种选择:
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)选项似乎最有意义。如果你还有两个键,为什么不更新/删除它们?
答案 1 :(得分: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;}
会将x
评估为时显式更改为布尔。因此,只要您测试的是data[key1][key2] == false
,x
就应该是假的。
但是,您需要小心这一点,因为x
比原始值更少虚假。例如。即使在如上所述分配valueOf之后,隐式强制仍然看起来很简单......
(x ? 'yes' : 'no')
"yes"
答案 2 :(得分:1)
你可能从其他答案中得到了你需要的东西,但总结一下:
我的问题是:有没有办法删除基础对象
没有。您可以删除对它的所有引用,以使其可用于垃圾回收。当垃圾收集器运行时(在某个未指定的时间),它将删除该对象。
或用falsey覆盖它,以便上面的两个属性都会评估为falsey?
不完全是。您只能为每个属性分配一个新值,以便它们计算为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())
。无论什么都适合。