我正在尝试创建一些树结构。
我希望访问我的数据如下:
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?
这样想:
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)选项似乎最有意义。如果两个密钥都有,为什么不同时更新/删除呢?
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"
你可能已经从其他答案中得到了你需要的东西,但总结一下:
我的问题是:有没有任何方法可以删除底层对象
否。您可以删除对它的所有引用,使其可用于垃圾收集。当垃圾收集器运行时(在某个未指定的时间),它将删除对象。
或者用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())
。随便什么。