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

时间:2013-11-10 04:15:12

标签: javascript node.js websocket equality

我有一个对象,其中键是WebSockets(来自Node.JS ws库)。

假设我有两个不同的WebSockets(" Socket A"和" Socket B")。

socketa === socketb // => false

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

theObject.hasOwnProperty(socketa) // => true

问题在于:

theObject.hasOwnProperty(socketb) // => true

尽管这些是两个不同的对象(彼此!==),但它们是对象中的 键,仅Socket A是的键

key in object相同的结果:

socketa in theObject // => true
socketb in theObject // => true

对象中肯定只有一个成员:

Object.keys(theObject).length // => 1

这里发生了什么?

3 个答案:

答案 0 :(得分:2)

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

当您查找密钥时,.hasOwnProperty()也是如此。所以,你基本上会这样做:

theObject.hasOwnProperty("[object Object]")

所有套接字,因此它们看起来都一样。

您可以通过为套接字提供某种唯一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;
     }
 })();

答案 1 :(得分:0)

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

编辑:

MDN reference for the in operator.
MDN reference for the hasOwnProperty() method

测试属性的两种方法都将使用属性 name 作为字符串,但hasOwnProperty()不会像in那样检查原型更改。

答案 2 :(得分:0)

hasOwnProperty接受一个字符串参数,即属性的名称。你正在传递套接字,这不是你想要的。它应该定义为{"socket": socketa},然后测试theobject1["socket"] === theobject2["socket"]