So, I have a JSON string, and I intend to parse it, and alert the contents, like so.
var json_string = '[1,2,3,4,5]';
var parsed_string = JSON.parse(json_string);
for(x in parsed_string) alert(x)
However, not only do I get the five elements, I get a whole bunch of extra crud I didn't ask for... $constructor, $family, append, associate, etc...
Is there any way I can iterate through this array without hitting these extra values?
Edit: For those wondering - I later realized that parsed_string.length returns the proper array length for me to iterate over.
for in loops over all enumerable object properties; which in the case of an array in Javascript, is all elements, and all methods/ attributes you've added to the array instance, or to any object in the prototype chain.
This is the one single reason you should use for ;;; for looping through arrays.
var json_string = '[1,2,3,4,5]';
var parsed_string = JSON.parse(json_string);
for(var i=0;i<parsed_string.length;i++) alert(parsed_string[i]);
You should loop through a JavaScript object like this:
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
alert(obj[key]);
}
}
.hasOWnProperty() ensures that the property specified by key is not inherited. However, you're dealing with an array here:
for (var i = 0; i < arr.length; i++) {
alert(arr[i]);
}
Related
This is something very basic I might be missing here but I haven't seen such result till now.
I have a for loop where options.headers.length is 3. And in for loop I am dynamically creating a table header. Ideally this loop should run three times for 0 1 and 2 but when I have printed index it's printing 0,1,2,clean and remove. I haven't seen clean and remove as indexes. I know this information is not sufficient enough but if you have any clue please suggest. something might be overriding this is all I am concluded too after my debugging.
for (index in options.headers)
if you don't want to iterate clean and remove then change the loop to:
for (var i=0; i< options.headers.length;i++){
//use i for getting the array data
}
if you use for (index in options.headers) it will iterate for non-numeric keys also.
don use just index (as that is = window.index = global = bad) use var index
(read more here https://www.google.pl/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=globals+javascript+bad)
you have to check does the array has it as own property or maybe its some function (more after answer)
for (var index in options.headers) {
if (options.headers.hasOwnProperty(index) {
// code here
}
}
more about #2:
let's say we have
var array = [0,1,2,3];
and besides that, extending array with function (arrays can have functions in javascript and strings too)
Array.prototype.sayHello = function() {
alert('Hello');
};
then your loop would print sayHello as part of the array, but that's not it's own property, only the arrays
I assume that options.headers is an Array?
This happens when you (or some framework you load) adds methods to the Array prototype. The "for in" loop will enumerate also these added methods. Hence you should do the loop for an array with:
for (var i = 0; i < options.headers.length; i++)
That way you will only get the real values instead of added methods.
This is the array:
{"C8_235550":
{"listing":"aut,C8_235550_220144650654"},
"C8_231252":
{"listing":"aut,C8_231252_220144650654"}}
It was fetched with a GET request from a Firebase database using Google Apps Script.
var optList = {"method" : "get"};
var rsltList = UrlFetchApp.fetch("https://dbName.firebaseio.com/KeyName/.json", optList );
var varUrList = rsltList.getContentText();
Notice the .getContentText() method.
I'm assuming that the array is now just a string of characters? I don't know.
When I loop over the returned data, every single character is getting pushed, and the JavaScript code will not find key/value pairs.
This is the FOR LOOP:
dataObj = The Array Shown At Top of Post;
var val = dataObj;
var out = [];
var someObject = val[0];
for (var i in someObject) {
if (someObject.hasOwnProperty(i)) {
out.push(someObject[i]);
};
};
The output from the for loop looks like this:
{,",C,8,_,2,3,5,5,5,0,",:,{,",l,i,s,t,i,n,g,",:,",a,u,t,,,C,8,_,2,3,5,5,5,0,_,2,2,0,1,4,4,6,5,0,6,5,4,",},,,",C,8,_,2,3,1,2,5,2,",:,{,",l,i,s,t,i,n,g,",:,",a,u,t,,,C,8,_,2,3,1,2,5,2,_,2,2,0,1,4,4,6,5,0,6,5,4,",},}
I'm wondering if the array got converted to a string, and is no longer recognized as an array, but just a string of characters. But I don't know enough about this to know what is going on. How do I get the value out for the key named listing?
Is this now just a string rather than an array? Do I need to convert it back to something else? JSON? I've tried using different JavaScript array methods on the array, and nothing seems to return what it should if the data was an array.
here is a way to get the elements out of your json string
as stated in the other answers, you should make it an obect again and get its keys and values.
function demo(){
var string='{"C8_235550":{"listing":"aut,C8_235550_220144650654"},"C8_231252":{"listing":"aut,C8_231252_220144650654"}}';
var ob = JSON.parse(string);
for(var propertyName in ob) {
Logger.log('first level key = '+propertyName);
Logger.log('fisrt level values = '+JSON.stringify(ob[propertyName]));
for(var subPropertyName in ob[propertyName]){
Logger.log('second level values = '+ob[propertyName][subPropertyName]);
}
}
}
What you have is an object, not an array. What you need to do is, use the
Object.keys()
method and obtain a list of keys which is the field names in that object. Then you could use a simple for loop to iterate over the keys and do whatever you need to do.
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);
}
I am using array as an associative array of objects in which keys are ID number of objects in database. Quiet naturally- IDs are large numbers - so that means it is common to have array of length 10^4 with only 20 elements as valid real objects.
I want to send this data back to server but whatever plugins I had to convert js objects to JSON- I tried them all & they all produce a JSON string of length 10^4. So much data can't be sent back.
I need a way of converting associative array to JSON discarding undefined entries.
Any suggestions ?
EDIT:
Example of what my array looks like :
var myAssociativeArray = [undefined, undefined,undefined...., someobject, some other object ...,undefined, ... yet another....]
It sounds like you have a regular array, but you're using it as if it were sparse (which it may or may not be internally). Here's how to use a replacer function that will convert to an object:
JSON.stringify(root, function(k,v)
{
if(v instanceof Array)
{
var o = {};
for(var ind in v)
{
if(v.hasOwnProperty(ind))
{
o[ind] = v[ind];
}
}
return o;
}
return v;
});
Reading your question, it looks are using an array. Here's one solution to get only the defined entries of the array (order not guaranteed).
Note that since it is a sparse array and can go upto 10000 for instance, it's better to only enumerate the properties and not actually loop from 0 to 9999, as most of them will be undefined anyways. So this is better for performance.
var definedEntries = {};
for(var prop in dataObject) {
if(dataObject.hasOwnProperty(prop)) {
definedEntries[prop] = dataObject[prop];
}
}
Then send definedEntries to the server.
I'm not a javascript guru. I've got the following code below:
var aCookieValues = sCookieContentString.split('&'); // split out each set of key/value pairs
var aCookieNameValuePairs = aCookieValues.split('='); // return an array of each key/value
What I'm trying to do is split the first string via & and then create another array that takes the first array and splits it further via the = character that exists in every value in the aCookieValues array
I get the error aCookieValues.split is not a function.
I've seen an example that basically does the same thing but the second time this guy is using a loop:
(http://seattlesoftware.wordpress.com/2008/01/16/javascript-query-string/)
// '&' seperates key/value pairs
var pairs = querystring.split("&");
// Load the key/values of the return collection
for (var i = 0; i < pairs.length; i++) {
var keyValuePair = pairs[i].split("=");
queryStringDictionary[keyValuePair[0]] = keyValuePair[1];
}
Ultimately what I'm trying to achieve here is a final dictionary with key/value pairs based off the '=' split. I'm simply trying to split up a cookie's values and shove it into a nice dictionary so I can then get certain values out of that dictionary later on.
You are getting this error because aCookieValues is an array, and it does not have a split method. You would need to call the split method on each element of aCookieValues:
var aCookieValues = sCookieContentString.split('&');
for (var i = 0; i < aCookieValues.length; i++) {
var aCookieNameValuePairs = aCookieValues[i].split('=');
// Handle aCookieNameValuePairs[0] as the key
// Handle aCookieNameValuePairs[1] as the value
}
To shove everything in your nice dictionary, simply declare it before the for loop: var myDict = {}, and then put the following after the split('=') call:
myDict[aCookieNameValuePairs[0]] = aCookieNameValuePairs[1];
EDIT: Which, after reading your question properly, is the same method used in the code snippet you supplied. I hope at least this explains how that works :)
In your second line you are attempting to call split() on an array, when it is a function defined on strings.
Example:
"a=1&b=2&c=3".split('&') returns an array ['a=1','b=2','c=3']
Your code would then call split on the array:
['a=1','b=2','c=3'].split('=')
But that function doesn't exist. It seems like your goal is to split each string in the array, so the example you gave in the question seems appropriate - loop through each element and split it.
split operates on a string. You're trying to split aCookieValues, which is an array. The example you cite is looping through the array, and then splitting each element as a string.
Just for fun, one way to deal with this would be to use a map function, which performs an action on each element of an array, and emits an array as a result. If you make a generic map function available to all your arrays, like this:
if (!Array.prototype.map) { // don't step on anyone's toes
Array.prototype.map = function( f ) {
var result = [];
var aLen = this.length;
for( x = 0 ; x < aLen ; x++ ) {
result.push( f(this[x]) );
}
return result;
};
};
...you can call it as a method on your array directly. Thus:
yourstring = 'x=3&y=4&zed=blah&something=nothing';
dictionary = yourstring.split('&').map( function(a){ return a.split('='); } );
dictionary will now be a nice clean array of (arrays of) name/value pairs, like this:
[["x", "3"], ["y", "4"], ["zed", "blahblah"], ["something", "nothing"]]
If your use case becomes complex, an approach like this can be a nice abstraction. Of course, you can arrange these data in other structures if needed, either by playing with a function passed into map, or processing in a separate pass.