1

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

假设我有两个不同的 WebSocket(“Socket A”和“Socket B”)。

socketa === socketb // => false

Socket 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

这里发生了什么?

4

3 回答 3

2

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

.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;
     }
 })();
于 2013-11-10T04:26:12.920 回答
0

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

编辑:

运营商的 MDN 参考in该方法
的 MDN 参考hasOwnProperty()

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

于 2013-11-10T04:21:00.390 回答
0

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

于 2013-11-10T04:27:01.377 回答