Javascript 两个不同的对象在用作对象中的键时被视为相同的对象

Javascript 两个不同的对象在用作对象中的键时被视为相同的对象,javascript,node.js,websocket,equality,Javascript,Node.js,Websocket,Equality,我有一个对象,其中键是WebSocket(来自Node.JSwslibrary) 假设我有两个不同的WebSocket(“套接字A”和“套接字B”) 套接字A是对象中唯一的键: theObject.hasOwnProperty(socketa) // => true Object.keys(theObject).length // => 1 问题是: theObject.hasOwnProperty(socketb) // => true 即使这是两个不同的对象(彼此!=

我有一个对象,其中键是WebSocket(来自Node.JS
ws
library)

假设我有两个不同的WebSocket(“套接字A”和“套接字B”)

套接字A是对象中唯一的键:

theObject.hasOwnProperty(socketa) // => true
Object.keys(theObject).length // => 1
问题是:

theObject.hasOwnProperty(socketb) // => true
即使这是两个不同的对象(彼此
!=
),但它们都是对象中的键,只有套接字A是其键

与输入对象的
结果相同

socketa in theObject // => true
socketb in theObject // => true
对象中肯定只有一个成员:

theObject.hasOwnProperty(socketa) // => true
Object.keys(theObject).length // => 1
这里发生了什么?

hasOwnProperty()方法使用属性名。如果WebSocket对象以相同的方式转换为字符串,则它们都将满足
hasOwnProperty(propName)
。因此,在这两种情况下,属性名都在对象中

编辑:



属性的两种测试方法都将使用属性名称作为字符串,尽管
hasOwnProperty()
不会检查原型,而
中的
会改变这种方式。

将属性指定给对象时,属性的键是字符串。如果您将套接字之类的东西作为键传递,那么javascript将努力将其转换为字符串并将其存储为键。如果WebSocket对转换为字符串的
toString()
方法没有特殊支持,那么您将获得一些通用转换,例如
[object object]
,这意味着您的所有WebSocket将显示为相同的属性

当您查找密钥时,
.hasOwnProperty()
也是如此。因此,你基本上要做:

theObject.hasOwnProperty("[object Object]")
对于所有的插座,它们看起来都一样

您可以通过为套接字提供某种唯一ID来解决这个问题,然后使用该ID作为密钥,您可以将套接字本身作为映射对象中的数据

例如,您可以这样做:

function addSocketToMap(socket, obj) {
    if (!socket.uniqueKey) {
        socket.uniqueKey = addSocketToMap.cntr++;
    }
    obj[socket.uniqueKey] = socket;
}
addSocketToMap.cntr = 0;

function isSocketInMap(socket, obj) {
    if (socket.uniqueKey) {
        return obj.hasOwnProperty(socket.uniqueKey);
    }
    return false;
}

var theObject = {};
addSocketToMap(socketA, theObject);
addSocketToMap(socketB, theObject);

var a = isSocketInMap(socketA, theObject);   // true
var b = isSocketInMap(socketB, theObject);   // true

如果这不会对WebSocket对象的实现造成任何问题,您也可以只重写其toString:

 (function() {
     var cntr = 0;
     WebSocket.prototype.toString = function () {
         // add a uniqueKey if it doesn't already exist
         if (!this.uniqueKey) {
             this.uniqueKey = cntr++;
         }
         // make a unique string identifier
         // that will look like "WebSocket_xxx"
         return "WebSocket_" + this.uniqueKey;
     }
 })();

hasOwnProperty
接受一个字符串参数,即属性的名称。你正在通过插座,这不是你想要的。它应该定义为
{“socket”:socketa}
,然后测试对象1[“socket”]==对象2[“socket”]

是否有意义。但是,我的代码仍然使用“in”,结果仍然相同。使用
in
也会将对象转换为字符串。在
中使用
propName与使用
hasOwnProperty(propName)
的情况相同。在这两种情况下,值都转换为字符串。嗯,好的。我可以扩展WebSocket的原型,使
toString
返回某种特殊的ID吗?@JJ56-您可能可以,但由于我不知道修改WebSocket对象是否安全,我建议使用另一种实现,只为它们添加一个唯一的属性。看我的答案的补充。太好了,谢谢!我将尝试使用
toString
(我相信我的其余代码可以保持不变),并在需要时使用您的解决方案。@JJ56-请记住
toString(
)必须为每个
WebSocket
对象生成唯一且可重复的字符串(这意味着你可能必须像我上面所做的那样在套接字中存储你生成的任何字符串)。当然。你使用计数器的系统可能工作得很好。