Reputation: 551
I am using socketio 0.9 to create a complex program and in order to store all the sockets id, i am using arrays like this:
var clients = {};
I am using my own serial to identify my sockets and store them in my array, and then i am setting the 'socket' key, with its real value.
clients[serial] = { "socket": socket.id };
Now i need to get all sockets id from my array without its serial. How can i do it?
I am trying with this iteration, but i donw know how to get the socket atribute:
for(var c in clients) {
c.socket
}
Thanks.
Upvotes: 1
Views: 1212
Reputation: 5881
First of all, clients
is not an array but an object.
You can get all keys with Object.keys()
or with a little help from lodash
you can use _.keys
or if you are only interested in the socket ids:
let _ = require('lodash');
console.log(_.map(clients, 'socket');
Upvotes: 0
Reputation: 3331
While PHP calls that an associative array, it is just an object (also called hash) in JavaScript, and a hash table or hash map in theoretical computer science.
That being said, the for ... in
instruction iterates over the keys of an object, not over its values:
var clients = {
clientid1: { name: "John Doe", age: 42 },
clientid2: { name: "Jane Doe", age: 34 }
};
for (var key in clients) {
console.log(key);
}
Console output:
"clientid1"
"clientid2"
Therefore, to access the values of your clients hash, like the socket
property, iterate it like this:
for (var serial in clients) {
clients[serial].socket.sendSomethingViaTheSocket(...);
}
for ... in
seems to work, why do other solutions even exist?Since JavaScript is a very dymanic language featuring prototypal inheritance, you can add, change, and remove properties of pretty much every JavaScript object, and add new properties and methods to object prototypes (the "blueprint" of what methods and properties objects of a certain "class" have).
This means that this is fully valid JavaScript code:
HTMLElement.prototype.isParagraph = false;
HTMLParagraphElement.prototype.isParagraph = true;
var myElement = document.querySelector(...);
if (myElement.isParagraph) {
// that's possible in javascript!
}
Since extending the prototype is allowed for most objects in JavaScript, it is also possible for the Object
prototype, which is the ancestor for all non-value objects. Let's say you want to define your own method for adding a property to an object (why ever you would decide to do this):
Object.prototype.addProperty = function (name, value) {
this[name] = value;
};
var exampleCustomer = { name: "John Doe" };
exampleCustomer.addProperty("age", 42);
console.log(exampleCustomer.age); // logs 42 on the console
But this means that every object in JavaScript from now on has a addProperty
method, therefore when you use for ... in
, you will not get the result you expect:
for (var key in exampleCustomer) {
console.log('key ', key, ' equals ', exampleCustomer[key]);
}
Console output:
key name equals John Doe
key age equals 42
key addProperty equals function (name, value) { ... }
^ oops!
You will now find that for ... in
also iterates over properties set on the prototype chain of the object you want to iterate over. This means that using for ... in
is fine if, and only if, you can be sure that nobody alters your prototypes.
Since ES5, there exist two methods to mitigate that problem. Meet Object.defineProperty
and Object.defineProperties
. Should you ever need to define methods on prototypes, use these methods:
Object.defineProperty(
Object.prototype, // the object the property should be defined on
"addProperty", // name of the property
{
enumerable: false, // should the property show up in for ... in / Object.keys()?
writable: true, // can the value of this property be changed with obj.addProperty = ..?
configurable: true, // can this property be changed with another defineProperty call?
value: function (name, value) { this[name] = value; }
}
);
When you define a property with configurable: false
, it will not show up in a for ... in
loop.
If you don't want to use a library to work around the problems described above, you can use some methods included in vanilla JavaScript.
Object.keys
and Array.prototype.forEach
:
Object.keys(clients).forEach(function (key) {
clients[key].socket.sendSomething();
});
// will NOT iterate over prototype-inherited properties
ECMAScript2015/ECMAScript6 for ... of
: (works in node 4+ and new browsers, no IE)
for (let clientid of clients) {
clients[clientid].socket.sendSomething();
}
// also does NOT iterate over prototype-inherited properties
You can also use Array.prototype.map
and arrow functions in node 4+ to get the sockets of all clients in a very readable way:
let clientSockets = Object.keys(clients).map(k => clients[k].socket);
// clientSockets contains the socket of all clients now
Underscore / lodash:
_.each(clients, function (client) {
client.socket.sendSomething();
});
jQuery:
$.each(clients, function (id, client) {
client.socket.something();
});
AngularJS:
angular.forEach(clients, function (client, id) { // order is different than with jQuery!
client.socket.something();
});
Upvotes: 1
Reputation: 847
You can create an array of all socketIds you saved like this :
var arr = [];
Object.keys(clients).forEach(function(s){
arr.push(clients[s].socket)
});
console.log(arr); // arr would have all socketIds
Here Object.keys() returns an array of all serials in clients which is then used to iterate and find each socketId vaues you saved
Upvotes: 0