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

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

说我有两个不同的WebSockets(“套接字A”和“套接字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 

这里发生了什么?

将属性分配给对象时,属性的键是一个string。 如果你传递一个像套接字这样的密钥,那么JavaScript将尽力将其转换为一个string并将其存储为一个密钥。 如果WebSocket没有特别的支持toString()方法来转换为string,那么你会得到一些通用的转换,比如[object Object] ,这意味着所有的WebSocket都将显示为相同的属性。

.hasOwnProperty()在查找关键字时也是如此。 所以,你基本上会这样做:

 theObject.hasOwnProperty("[object Object]") 

所有的sockets,因此他们都看起来一样。

你可以通过给你的套接字一些独特的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接受一个string参数,即属性的名称。 你传递的是socket,这不是你想要的。 应该像{"socket": socketa}那样定义,然后testing{"socket": socketa} theobject1["socket"] === theobject2["socket"]

hasOwnProperty()方法有一个属性名称。 如果WebSocket对象以相同的方式转换为string,则它们都将满足hasOwnProperty(propName) 。 所以在两种情况下属性名称都在对象中。

编辑:

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

这两种testing属性的方法都将使用属性名称作为string,虽然hasOwnProperty()不会检查原型的改变方式。

Interesting Posts