Reputation: 558
So recently I had to check if a user had a certain plugin installed, which is apparently quite easily done:
if(typeof navigator.plugins['plugin name'] === 'undefined'){
alert('Please install plugin')
}
This isn't surprising to me, I thought it just accessed the object assigned to plugin name
of the plugins
object. (like plugins['plugin name'] = {...}
)
The strange thing is, if you console.log
the navigator.plugins
variable, it comes out as such:
>PluginArray
>0: Plugin
>1: Plugin
>2: Plugin
So, these Plugin objects are accessible by using both navigotor.plugins['Plugin name']
and navigator.plugins[i]
!
My question is, how can I achieve something similar, so I can access objects of an array both by index (easy iteration and preserving array functionalities) and by a property of said objects (easy accessing by id or name)?
The navigator.plugins object has the PluginArray
prototype, so I suppose this class it somehow overrides the obj['index']
accessor and looks for the object(s?) that have the given index as their 'name' property, either by iterating when accessing, maintaining an internal array that maps the numeric indexes to the names ([i] = 'index')or an internal object that maps names to their index (.index = i).
So any thoughts on the best approach?
EDIT: as pointed out by Oriol, you can assign the same object to both keys (arr[0] = arr[obj.name] = obj
) and this can work quite well if obj.name is unique, if it is not you risk overriding the key that was set earlier. Definitely a cheap and easy solution if you want to use something like a unique database index as second key.
Upvotes: 1
Views: 327
Reputation: 175748
This is the same behaviour that DOM collections implement; internally if the passed key is an int forward it to .item()
if its a string forward it to .namedItem()
.
The closest you can get currently to this is an ES6 Proxy()
with very limited support;
"use strict";
let Plugins = new Proxy(
[{name: 'pdf', mime: 'pfft/pdf'}, {name: 'swf', type: 'flash'}],
{
get: function(obj, prop)
{
if (!isNaN(prop)) // by index
return obj[prop]
for (var k in obj) // lookup a name
if (obj[k].name == prop)
return obj[k];
}
});
console.log(Plugins); // Array [ Object, Object ]
console.log(Plugins[0]); // Object { name: "pdf", type: "doc" }
console.log(Plugins['pdf']); // Object { name: "pdf", type: "doc" }
Upvotes: 1
Reputation: 780688
navigator.plugins
has a prototype PluginArray
, which links to native code that translates plugin names to entries in the array.
Use console.log(navigator.plugins.__proto__)
to see this.
Upvotes: 0
Reputation: 287960
You can assign the same value to multiple properties:
var obj = {};
obj[0] = obj.name0 = value0;
obj[1] = obj.name1 = value1;
obj[2] = obj.name2 = value2;
Upvotes: 2
Reputation: 2938
An Array is at it's most basic an Object extended with a magic length
key - you can add any key values to it you'd like. Iterating through it becomes slightly more complicated if you want to see the keys, and setting anything that can equate to a number (ie arr["1"]
) will equate to setting a number index of the array.
Upvotes: 0