what's the best way in JavaScript to store values in an assoziative array? I tried a lot of things and it always brakes somehow.
I tried something like:
var test = [];
for(var prop in json) {
test[prop] = json[key];
}
this works and i get a cool array then i can actually use. However calling test.length gives me 3 when there should be 10 items, it sometimes gives me 0 when there should be at least 8 items.
What do i do wrong? What's the best way to go here to get an assoziative array going which i can use properly like in Java?
Everything is an object in JavaScript. foo['bar'] is the same as foo.bar. Array is just an object with some predefined methods that let it emulate what you would call a numeric array in PHP or just an array in almost any other language. JavaScript objects work like associative arrays in PHP. The general non-PHP name for it is hash.
So, to address your problem with length, it is a predefined property of an array object. Using it on an object that isn't an array will not give you the results you are expecting. To count the number of properties in an object, you can use
Object.keys(obj).length
in modern browsers. keys() function gets an array of keys from a hash, so it will have a correct length property.
If you wish to support older browsers, you have to iterate through object properties and count them manually. Be aware that for (var prop in json) will also iterate through the properties of every object in the prototype chain, so you might want to check if a property is object's own property using hasOwnProperty() method.
Related
Basically everything is said with the title: how to get the object from array by object's property value which is unique by the way?
Situation:
My current strategy is that I gave id attribute to the div of that object's property id (all ids are unique, take a look at Array of objects below) which looks like this:
<div id="3590" class="my-div"></div>
Now, when this div is clicked, I'll get the id attribute and I need to find the right object because I also need to get some other properties and also make some changes to some properties.
Why Im doing this:
This seems to be the only way because as I was told in other question that there's no way to access the object, even when this div is one of the object's properties (take a look at Array of objects below).
If that's not true, please let me know. This is super important!
Array of objects:
0: myObject
__e3_: Object
div: div#3590.my-div
gm_accessors_: Object
gm_bindings_: Object
id: 3590
latlng: _.K
map: _.ng
uh: Object
__proto__: c
1: myObject
__e3_: Object
div: div#3591.my-div
gm_accessors_: Object
gm_bindings_: Object
id: 3591
latlng: _.K
map: _.ng
uh: Object
__proto__: c
//thousands of objects
There can be thousands of objects in that array and that's why I added word "fastest" to the question: Im concerned about the performance because there's also other stuff going on.
Also, I prefer vanilla JS because Im currently learning it but if you know a good and fast way in jQuery, please go ahead, I'll convert it myself.
More details:
Objects are in array because I also need to iterate them (more often than working with them one-by-one)
All one-by-one actions are done via click events (user triggered and there's some protection: only one action at a time)
Keep reference to the corresponding object in the element as well.
So, whenever you click an element, the element object itself will have the reference to corresponding object. No need to find from the array.
And yes please be careful with name collisions. Assign object to new key so that object doesn't replace value of element object's existing key.
For old browsers, I am not sure they can even render thousands of elements.
Example:
var element = document.createElement("div");
element.myObj = {id: 3306, name: 'coolBoy'}; //make sure key, 'myObj' in this case, doesn't already exist.
var myArray = [];
myArray.push(element.myObj); //if you need to keep in array as well.
element.onclick = function(e){
console.log(e.currentTarget.myObj.name);
};
I'd recommend using a Map collection - it allows for both fast iteration and fast access by key, and is a builtin data structure.
If you don't want to go down the ES6 route (and not use a shim either), a reasonably fast approach would be to keep the array sorted. You can use binary search to access single elements.
Notice that for a thousand objects, there probably won't be an observable difference anyway. Don't prematurely optimise. Just keep your API to access the collection clean so that you can easily swap out the data structure in the future, should there be any need.
function getObjectFromId(id) {
return ARR.filter(function (obj) {
return obj.id === id;
})[0];
}
I am getting a model deferred object with a structure like this:
How can I find out how many objects are present inside this object (in this case, three). If I use Object.keys(myObject).length, it includes the object observer and other data also like _computeBindings,_bindings etc. I have even tried to use hasOwnProperty while calculating the length but its not giving me desired result.
One way I can figure out is to iterate over the index and get the last index value like this:
can.each(myObject,function(myObject,index){
// Get the last index value and put it into some variable
});
Is there an API for this?
can.Map has a keys function that will give you an Array of the keys in your Map and from that you can get how many Objects by checking that Array's length.
Using a can.List as your data structure would also work. The keys in your data are numeric and you need to check the length, all things that can.List is built for.
Try using myObject.attr('length')
The model _data attribute contains a copy of just the model without the bindings. The easiest way to do this is to use:
Object._data.length
ive got a problem getting parameters from a json chain, the json I got looks something like this
[{"aa":"bb","ccc":"ddd","eeee":"ffff","ggggg":"hhhhh","iiiiii":"jjjjjj","kkkkkkk":"lllllll"}]
Im trying to count how many pairs there are inside the '{}' but i dont know how. I tried json.length and json[0].length, the first one gave me back the value '1' and the second one undefined.
Your json object is an array containing one object. So the length is 1. The object in the array has multiple properties (key/value pairs).
So in most modern browsers (except IE), this would work for you:
Object.keys(json[0]).length
Check out the answers here of various techniques for iterating/counting properties of an object in JavaScript:
How to efficiently count the number of keys/properties of an object in JavaScript?
I don't understand how this works:
var links = [].slice.apply(document.getElementsByTagName('a'));
It creates an empty array but I don't completely get the rest. What do slice and apply really do together in this script?
document.getElementsByTagName() and similar DOM methods return an array-like structure, a node list, instead of a true array. This is a common trick to convert it into a true array. It is also commonly used with the arguments special variable, another array-like structure. The slice method of the Array object would normally expect an array, and returns an array, but this way you can pass in something that is not technically an array. A slightly more readable, and arguably better version is this:
Array.prototype.slice.apply(document.getElementsByTagName('a'));
This basically converts the nodeList object retrieved from the getElementsByTagName into regular javascript array, to be able to use array methods on it.
If you do console.log($('some selector')) in the browser, it returns what looks like an array (first line):
But notice that it's not an instanceof Array, but it's actually the jQuery object.
When you do console.dir($('h1')), it shows it's actually the jQuery object.
The question is, how are they making it look like it's an array in the web console? I noticed in the jQuery source here they add reference to a few Array and Object methods, and here they add toArray (and slice and others) to the jQuery object. Is the web console somehow checking for these methods and if it finds one (toArray, indexOf, slice, etc.), it prints it as an Array? I would like to get this behavior out of any custom object, such as the Ember.ArrayProxy. Currently when you log the Ember.ArrayProxy it shows > Object or whatever, but it would be nice to show it as an array.
Any ideas?
You make your object inherit Array using the prototype, like so:
function SomeType() {
this.push(16);
}
SomeType.prototype = [];
SomeType.prototype.constructor = SomeType; // Make sure there are no unexpected results
console.log(new SomeType()); // Displays in console as [16]
And, of course, all jQuery objects are instances of the jQuery function/constructor, so that's how jQuery does it. As a bonus, because of the inheritance, you get all the methods from Array, and the indexing that comes with it too!