Javascript Arrays In IE 8 issue - javascript

As per what I know, arrays in Javascript is nothing but the combination of methods and objects.
Now my task is to display the values of array (say y_array)
I have used for(x in y_array) and then displayed the value.
In mozilla and in IE its working fine, but in IE it displays the first element of array with index as indexOf and value is indexOf(obj, from) which i dont want.
I tried
if(x!='indexOf') { display the array value ; }
It worked and things were fine but there is extensive use of arrays been displayed and I am looking for some permanent fix rather than this hardcoded one.
Can anyone please help me?

You are not the first mixing up arrays and objects. SO should contain a FAQ for this kind of questions ;)
Let's try to explain things:
An array is a row of values, which can be retrieved using their position in the row. The order of the array values is fixed (and may be reordered).
An object is a variable that contains named properties in the form of key-value pairs. The order of the key-value pairs belonging to an object is arbitrary.
An array looks like: [ 'first', 'second', 'third', ..., 'nth' ]
An object looks like: { first:'firstvalue', second:'secondvalue', ..., nth:'nthvalue' }
The first element of an array is the element with index 0 (so the first position in the row has index value 0). You retrieve it using myArray[0]
An object is unordered, so it has no first element. You retrieve any element from it using myObject.somekey or myObject['somekey'].
For arrays you use a loop iterating through the numbered index until the end of the array is reached:
var i=0, len = myArray.length;
for ( i; i<len; i++ ) {
//do something with >>> myArray[i] <<<
}
For objects you use a loop using the key and the in operator (making sure you are only retrieving user defined properties of the object with the .hasOwnAttribute method):
for ( var key in myObject ){
if (myObject.hasOwnProperty(key)) {
// do something with >>> myObject[key] <<<
}
}
Basically, think of an array as a cupboard with drawers, each containing a value. An object can be imagined as a pile of boxes with stickers on the lid, describing the content of the box. Retrieving something from an object, you ask: is there a box with sticker y in pile x and if so, what's in it? Retrieving something from an array, you ask: please give me the contents of drawer nr x.
Now as to your question: the array you are retrieving values for with a for..in loop contains a user defined method, namely indexOf. Using the object style loop for it, the array is treated as object, and the indexOf key (with value like function(){...} I bet) is shown too. IE That's why it may be better to use a traditional for loop with a numeric index when iterating over arrays.
Why is this only in IE? In modern browsers indexOf is a native method of the Array prototype, and native methods are not shown (unless you loop through their prototype that is). IE < 9 doesn't have a native indexOf method for arrays. Somewhere in the scripting you use the method has been added to the Array prototype as a user defined extension.
Bottom line for your problem: don't use for ... in to loop through the values of an array.

For arrays you should use this for loop:
var y_array = [1,2,3,4];
for (var i = 0; i < y_array.length; i++) {
var value = y_array[i];
// do what you want
alert(i + ': ' + value);
}
For objects (objects are like associative arrays - property: value) use this loop:
var y_array = { prop_1 : "value a", prop_2: "value_2", prop_3: 333 }
for (var key in y_array) {
var value = y_array[key];
// do what you want
alert(key + ': ' + value);
}

if there is no value in your json Object like jsobObj = {}. Then you got the indexOf prototype function in side the empty object in IE < 9. (with value like function(){...} I bet) is shown too.
Your can check a condition in side your for Loop. and skip that indexOf.
if(key =='indexOf'){continue;}
E.g :
var jsonObj = { key_1 : "value a", key_2: "value_2", key_3: 333 }
for (var key in y_array) {
if(key == 'indexOf'){continue;} // check if the array contain indexOf
var value = y_array[key];
// do what you want
alert(key + ': ' + value);
}

Related

Why can't you access this array with index?

Why does this array have a length property of 0? And as a follow up to that question, why can't you access an item in this array with an index value?
Consider the following:
var box = [];
box['material'] = 'cardboard';
box['size'] = 'small';
box.length; //0
console.log(box);
//[ material: 'cardboard', size: 'small' ]
box[0]; //undefined
However, when I do the following:
var box = [];
box['0'] = true;
box['1'] = 'cardboard';
box['2'] = 'some value';
box.length; //3
box[0];// true
Why does it output the correct length in this case, since '0' is a string and not a number and access the correct item with the 0 index?
In JavaScript, the length of an array is always one more than the largest numeric (integer) property name. Arrays can have properties whose names are not numeric, but they don't count towards the length of the array (and they are ignored in some other important situations).
Object property names are always strings, but strings that are non-negative integer values when interpreted as numbers are special in arrays. Accessing properties with numeric values works because the numbers are first converted to strings; thus box[0] and box['0'] do exactly the same thing.
when setting box['material'] it creates a property called 'material' with value 'cardboard'. this doesn't add a element to the list!
you need to use .push() or asign the index you want.
also, the '0' string is cased to a number, so obj['0'] and obj[0] is the same (not just for 0, this happens for all numbers)
I think you’re confusing objects with arrays. While arrays are indeed objects in javascript, that doesn’t help us here.
What you are trying to instantiate is an associative array with key-value pairs “material”->“cardboard”, “size”->“small”. However, such a datastructure does not exist in javascript. Array must only have integers as indexes, as in
box = [];
box[0] = 'material';
box[1] = 'someValue';
The reason why your code (which only seems to be an associative array)
box = [];
box['0'] = true;
box['1'] = 'cardboard';
works is because of implicit type conversion. Because you’ve declared box to be an array, a string is not valid in this position, so javascript quietly converts it into an integer, so you again get a plain, boring, integer-indexed array as above.
What you can do, though, is create an object with attributes. So you might, for example, state
box = {}; // box is now an object
box.size = 'small'; // box now has an attribute called “size”
// which has the (string) value “'small'”
box.material = 'cardboard';
or at one go using the notation for object literals:
box = {
size: 'small',
material: 'cardboard'
};
This is the closest you can get to associative arrays in javascript. Note that objects do not have a length. If you want to access the number of attributes they have, you have to use Object.keys(box).length. To iterate over the keys, use
for(var key in box){
console.log('value of ' + key + ' is ' + box[key])
}
Note the array-like notation here, but remember: You’re dealing with objects, not arrays, though dealing with them looks similar. Since box is of type object, you will not only get the attributes you have defined yourself, but also any attributes which are defined for every object. To get only the keys you put in there yourself, use
for (var key in box) {
if (box.hasOwnProperty(key)) {
// do stuff
}
}
If you need to add keys, i.e. attributes at runtime, use (for example)
//supposing that box was instantiated as above
var listOfBoxAttributes = ['shape', 'color', 'weight'];
for(var i in listOfBoxAttributes)
box[listOfBoxAttributes[i]] = undefined;

How to get all children of a subArray in Javascript

So here's my problem:
So this is what my array looks like, I have shown a fragment of it here (from the console window).
It's overall pretty basic right? Except for it's indexing. As you see the first has value "1" and let's say the second has value "4". As for it's subarrays, these have custom indexes too.
Therefore, the old fashioned:
for(i=0; i<array.length; i++){
someVar = array[i];
//do something
}
won't work.
I get the 1 or 4 from iterating through another array, so don't need to get those.
I want to get all subArrays(not the further nested subArrays, only the second level).
So basicly what I want is something like this(is there something like this?):
array[someIndex].children.forEach(
//do something with **this**
)
To make it more practical for you:
So I know that the first array has index 1. How can I get the values of cat1 and cat2 without knowing it has index 2 (this could also be 6 or 42 for example). In this case, the first array only has one subArray but I would like to make it work for multiple subArrays. (to clarify, select cat1, cat2 from the second level subarray with, in this case, index 2)
Thanks in advance, any help is appreciated!
Evoc
Those aren't arrays. You have
[ { "1": { etc...
which is an array containing an object containing multiple other objects. You can't really use a for(i=...) loop for this, because your keys aren't sequential. You should use a for ... in loop instead:
arr = [{"1":{....}}];
for (i in arr[0]) {
for (j in arr[0][i]) {
console.log(arr[0][i][j]['msg']);
}
}
Use Object.getOwnPropertyNames to get the properties ordered with the integer indices first, from smallest to greatest. Iterate them to get msg1.
var array = {"1":{"3":{"5":{"data":"someData","moreData":"someMoreData"},"msg1":"hello world","msg2":"foo equals bar"},"5":{"8":{"data":"someData","moreData":"someMoreData"},"msg1":"world hello","msg2":"bar equals foo"},"your_name":"jimmy","your_msg":"hello world"},"4":{"3":{"5":{"data":"someData","moreData":"someMoreData"},"msg1":"hello world","msg2":"foo equals bar"},"5":{"8":{"data":"someData","moreData":"someMoreData"},"msg1":"world hello","msg2":"bar equals foo"},"your_name":"billy","your_msg":"foo equals bar"}};
for(let key of Object.getOwnPropertyNames(array[1])) {
if(Object(array[1][key]) !== array[1][key]) break;
console.log('msg1 of "'+key+'": ' + array[1][key].msg1);
}
console.log('your_msg: ' + array[1].your_msg);
The example you showed it's an array with only one index, inside of this index there are nested objects, you could iterate them using the property iterator (foreach). You have to go to the second level tho, since the values you need are there.
for (var key in object) {
for(var anotherKey in object[key]) {
//check for undefined
if(object[key][anotherKey].hasOwnProperty('msg')) {
//code
}
}
}
{ } - declaring objects (literal)
[ ] - declaring arrays

json jquery filter javascript array

I have a json object array. I want to search the array and for each object, create a list of 'services' that is a comma-seperated list of all the keys which have a value of "yes".
The list of json objects with the services list is then displayed in html using jquery's each.
Its a large json file so I want to do it as efficiently as possible.
I already have the object's properties being accessed through jQuery's each (ie, obj.name)
-- so I think it should be possible to filter the services listed for each object using
jQuery's filter, and then display the key if the value is yes.
But it seems like a more efficient option would probably be to create a new javascript array, join the services with a value of yes and then add that variable to the html being
appended.
Im not sure which would be faster and so far havent been very successful at either... so any advice and examples would be very helpful.
Here's what the json array looks like:
[
{"name":"name1",
"service1":"y",
"service2":"y",
"service3":"n",
},
{"name":"name2",
"service1":"n",
"service2":"y",
"service3":"n",
},
];
If you just want to filter the array then use grep.
grep - Finds the elements of an array which satisfy a filter function. The original array is not affected.
http://api.jquery.com/jQuery.grep/
First off, delete trailing commas. Internet Explorer gets really, really confused by them. Anyway, I assume you don't want to "search" the array when you say "for each value"; you want to iterate through the array and parse it into a more usable list. The first method I'd suggest is just passing what you want as the array you desire, but if that's not an option, what you're looking for is some variant of this, which should be fairly efficient (jsFiddle example):
var json = [
{"name":"name1", "service1":"y", "service2":"y", "service3":"n"},
{"name":"name2", "service1":"n", "service2":"y", "service3":"n"}
];
var parsed = {};
for (var i = 0, iLen = json.length; i < iLen; i++) {
// Assuming all we need are the name and a list
var name;
var list = [];
for (var key in json[i]) {
var value = json[i][key];
// We need to hold on to the name or any services with value "y"
if (key === "name") {
name = value;
} else if (value === "y") {
list.push(key);
}
}
// Add them to the parsed array however you'd like
// I'm assuming you want to just list them in plain text
parsed[name] = list.join(", ");
}
// List them on the web page
for (var key in parsed) {
document.write(key + ": " + parsed[key] + "<br>");
}
That way you wind up with a display to the visitor of the services available and still keep an array around for further use if necessary.
jQuery.inArray() Search for a specified value within an array and return its index (or -1 if not found).
http://api.jquery.com/jQuery.inArray/
Or
http://api.jquery.com/jQuery.each/

Question about the for loop in javascript?

In the following code why the variable 'a' refer to the index rather than the value ?
for (var a in Values) {
alert(Values[a]);
}
That's by design. It's trivial to get a value in an array when you know its key, but it's much harder to get a key given a value. Values can be duplicated, so how do you know which key should be used? But a key's unique, so given a key, there's only ever one value to retrieve. So, the for loop will iterate over the keys, and it's trivial to get the associated value.
Think of a JavaScript Array as a normal Object with a special property named length (actually, it a bit more complex). So the for..in loop behaviour is identical as for other objects:
var a = new Array();
a[1] = "a";
alert(a.length); // 2
alert(a[0]); // undefined
a[1000] = "b"
alert(a.length); // 1001
a[-1] = "c";
alert(a[-1]); // c
a.abc="why not";
for(var key in a)
{
alert(key+"="+a[key]);
}
// 1=a
// 1000=b
// -1=c
// abc=why not
Also note that you can have gaps within your array without having to pay the memory price.
There is a for each...in loop that does exactly that - enumerates only values. Coming soon to a browser near you.
for each(var a in Values) {
..
}
For arrays, there is a new function forEach which achieves the same.
someArray.forEach(function(value) {
..
});

JavaScript - Getting a name of an element in associative array

I have a JavaScript object that is treated as an associative array. Let's call it "fields". It has several elements, e.g.:
fields['element1'] = ...
fields['element2'] = ...
fields['element3'] = ...
Given fields[0], is it possible to obtain the name of the property (which is "element1") instead of its value?
Let's say you have an object oObject. It could be:
var oObject = {} ;
oObject["aaa"] = "AAA" ;
oObject["bbb"] = "BBB" ;
oObject["ccc"] = "CCC" ;
oObject["ddd"] = "DDD" ;
oObject["eee"] = "EEE" ;
Now, let's say you want to know its properties' names and values, to put into the variable strName and strValue. For that you use the "for(x in o)" construct, as in the following example:
var strName, strValue ;
for(strName in oObject)
{
strValue = oObject[strName] ;
alert("name : " + strName + " : value : " + strValue) ;
}
The "for(x in o)" construct will iterate over all properties of an object "o", and at each iteration, will put in variable "x" the current property name. All you have to do, then, to have its value, is to write o[x], but you already knew that.
Additional info
After some thinking, and after seeing the comment of Hank Gay, I feel additional info could be interesting.
Let's be naive (and forget the "in JavaScript, all objects, including arrays, are associative containers" thing).
You will usually need two kind of containers: Maps and Arrays.
Maps are created as in my example above (using the "o = new Object() ;" or the "o = {} ;" notation, and must be accessed through their properties. Of course, maps being maps, no ordering is guaranteed.
Arrays are created differently, and even if they can be accessed as maps, they should be accessed only through their indices, to be sure order is maintained.
Point is:
If you need a map, use a "new Object()" container
If you need an array, une an array, use a "new Array()" container
Don't EVER mix the two, and don't EVER access the map through indices, and for arrays, ALWAYS access its data through its indices, because if you don't follow those principles, you won't get what you want.
No, for two reasons.
fields[0] and fields["element1"] are different properties.
properties in an object are explicitly unordered
You could loop over the properties:
function (obj) {
for (prop in obj) {
if (obj.hasOwnProperty(prop) {
return prop;
}
}
};
…to get the "first" property for some arbitrary value of "first" that could change at any time.
http://ajaxian.com/archives/fun-with-browsers-for-in-loop explains the hasOwnProperty pattern.
There is no fields[0] (unless fields is an Array object, which supports numerical indices), so you can't get its name just like that. But you can simulate it like this:
function getKey(obj, i) {
var j = 0;
for (var p in obj) {
if (j++ == i) return p;
}
return null;
}
for (var p in obj) will loop through every field name in the object obj. By getting the nth field name, you can effectively get the "key" for a certain index.
Note that while it's working its way to become a standard, the order of field names is currently not guaranteed according to the standards, which means that after modifying the object, the same function call could theoretically return a different field name. Same thing goes that different browsers can return different results. Practically, you'll find that just about all the browsers do keep the order of field names so you shouldn't have to worry about it at all.
Just to point out what is implicit in everyone else's answer: "associative arrays" in Javascript are actually just Object instances, e.g.,
var aa = {};
aa.foo = 'argle';
alert(aa['foo']); // Will alert 'argle'
PLEASE don't use an Array instead of an Object—it has the potential to wreak havoc on for key in aa-style iteration.

Categories

Resources