当用作对象中的键时,两个不同的对象被视为相同
我有一个对象,其中的键是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()
不会检查原型的改变方式。