Defining Array in Javascript doesn't work as expected - javascript

The following code:
let s=[[],[]];
let k=0;
while (k<(JSON.parse(req.responseText).length)){
s[k][0] =dataBack[k].ModuleCode;
s[k][1] =dataBack[k].ModuleDescription;
k=k+1;
}
Should populate an array (s) with the data from an Ajax responce.
But this is not the case, since when k=2 (3d item) I get an error:
code.js:288 Uncaught TypeError: Cannot set property '0' of undefined
Searching on StackOverflow, I found this link:
How to create empty 2d array in javascript?
describing what I have done to declare my Array.
I am expecting the above code to store the returned values into the (s) array.
But I get the error described above.

Change your code a bit to add arrays as needed:
let s=[];
let k=0;
while (k<(JSON.parse(req.responseText).length)){
s.push([]);
s[k][0] =dataBack[k].ModuleCode;
s[k][1] =dataBack[k].ModuleDescription;
k=k+1;
}

Hope this makes it clear why you're failing:
let s = [ [], [] ];
// ^^^^ s[0] ^^^^s[1]

Javascript will let you ASSIGN to positions in the array that don't exist yet.
eg:
var a=[];
a[10]=12345;
console.log(a);
//Output: [ <10 empty items>, 12345 ]
However in your code you are ACCESSING the undefined position first and then trying to modify what is returned.
Adding an intermediate step it might clear up why it doesn't work:
let s=[[],[]];
let k=0;
while (k<(JSON.parse(req.responseText).length)){
var tmp=s[k]; //When k>=2 tmp is undefined.
tmp[0] =dataBack[k].ModuleCode; //Trying to add a property at 0 on undefined object
tmp[1] =dataBack[k].ModuleDescription;
k=k+1;
}
#Oleg has given a nice work around in his answer but using s.push([]) to ensure the value you are accessing is definite for before the subsequent modifications.
Alternatively you could assign an empty array directly s[k]=[] before modification.

Related

Hashmap values are not getting proprely using javascript

I am new to javascript . I created one hashmap in javascript
var usermap=new Map()
and then set the key value are
for(var i=0;i<data.lenght;i++) {
usermap.set(data.Id[i],[data.value[i],data.status[]i]
}
i set one key and multiple values now i want to get data.value of particular key. please help me out!
There are some typo in the code and some more errors, assuming this was what you wanted to achieve. The following errors were evident:
In the for loop data.length signifies it is an array
If data is an array, you cannot access it with data.Id,data.value or
data.status. Objects are accessed in this way.
If data is an object, then data.length would be undefined and it wouldn't loop.
var usermap=new Map();
var data = [{'Id':1,'value':'val1','status':true},{'Id':2,'value':'val1','status':true},{'Id':3,'value':'val1','status':true}]
for(var i=0;i<data.length;i++)
{
usermap.set(data[i].Id,[data[i].value,data[i].status]);
}
console.log(usermap.get(2)[0])

Javascript: Calling a function in an object literal

I'm learning to program in Javascript and I'd like some help/clarification.
I declared an array that contains animal names. I defined a function that I use to split a string in two. Then I create an empty object literal and add an animal and corresponding breed. I'm trying to invoke the separateWords function in the object literal, but I need some clarification. Here's my code:
var myPets = ["Bengal Bobcat", "Beagle"];
var separateWords = function (string) {
return string.split(" ");
};
var nameCollection = {};
nameCollection.cat = separateWords(myPets[0]);
nameCollection.dog = myPets[1];
nameCollection.fish = null;
When I enter console.log(nameCollection) I get the following:
Object {cat: Array[2], dog: “Beagle”, fish: null}
cat: Array[2]
0: "Bengal"
1: "Bobcat"
length: 2
However, when I enter console.log( separateWords(myPets[0])), I see:
[“Bengal”, “Bobcat”]
I don’t understand why the value of cat shows up as Array[2].
The console displays it as Array[2] as it would be (potentially) unreadable if it expanded it fully. One way to see everything is to stringify it using JSON.stringify which goes through each item in the object recursively and calls toString() on it:
var myPets = ["Bengal Bobcat", "Beagle"];
var separateWords = function (string) {
return string.split(" ");
};
var nameCollection = {};
nameCollection.cat = separateWords(myPets[0]);
nameCollection.dog = myPets[1];
nameCollection.fish = null;
document.body.textContent = JSON.stringify(nameCollection);
You are assigning to cat the result of the separateWords() function call, passing myPets[0] as a parameter.
separateWords() returns an array and with the myPets[0] input it returns a new array with the "Bengal" and "Bobcat" values splitted by the whitespace.
The split() function is the one creating an array with the splitted values and this result is returned by your separateWords() function, which also is the value assigned to the cat object member.
Each browser implements its console like it wants.
So your browser decided to implement the behavior you describe.
If you don't like it, propose a better idea to the developers of this browser. Or use another browser.
I am going to assume you are using Chrome Developer Tools or Firebug.
Developer tools condenses arrays and objects into easily readable lines you then inspect further with. What I mean is, you push the little arrow next each line in the console log to further inspect each object. I will use pictures to explain this.
Here I am assigning an array and then assigning an element in an object to that array as so:
As you can see when I log the object it show's an Array[2] rather than expand the array. In this next picture I then expand the array to inspect it.
Why is this exactly? My first thought is ease of readability. If you have an app that is complex and you have numerous debugging console logs, you can see all the logs on single lines making it easier to hunt down specific logs. As well, if you have a very large and complex object, it is arguably easier to read all the root elements on each line without expanding all the objects and arrays found within that object recursively.
String.prototype.split() returns an array containing the two values in the string which have been split. Read through this.
nameCollection.cat = separateWords(myPets[0])[0]; // nameCollection.cat == Bengal
nameCollection.cat = separateWords(myPets[0])[1]; // nameCollection.cat == Bobcat
This is simply how javascript (and many other languages) work. When you try to print "nameCollection" javascript doesn't automatically do a nice job of printing the cat array. Instead, it simply prints some type related information, which in this case is saying "cat" is an array of length 2.

JSON Parse splice issue

I can't seem to work out why splice isn't working correctly in this instance.
I have read countless stack overflow examples of splice and I can't seem to see an issue.
This code should basically remove index 14, from the first item(and only) in the JSON array.
var product_variations = JSON.parse('[{"0":"","1":"","2":"","3":"0.0000","4":"","5":"0.00","6":"0.00","7":"1.00","8":"0","9":"false","10":"false","11":[],"12":"","13":"","14":"Red","15":"Small"}]');
product_variations[0].splice(14, 1);
It does not work because splice is a method available on arrays, not on objects.
And this is an object:
{"0":"","1":"","2":"","3":"0.0000","4":"","5":"0.00","6":"0.00","7":"1.00","8":"0","9":"false","10":"false","11":[],"12":"","13":"","14":"Red","15":"Small"}
Actually you get an error like:
TypeError: undefined is not a function (evaluating 'product_variations[0].splice(14, 1)')
You can use delete instead or convert it to an array:
delete product_variations[0]["14"]
To convert it to an array you could try:
function objectToArray(p){
var keys = Object.keys(p);
keys.sort(function(a, b) {
return a - b;
});
var arr = [];
for (var i = 0; i < keys.length; i++) {
arr.push(p[keys[i]]);
}
return arr;
}
var product_variations = JSON.parse('[{"0":"","1":"","2":"","3":"0.0000","4":"","5":"0.00","6":"0.00","7":"1.00","8":"0","9":"false","10":"false","11":[],"12":"","13":"","14":"Red","15":"Small"}]');
var arr = objectToArray(product_variations[0]);
arr.splice(14, 1);
Use the "delete" keyword in Javascript.
delete myArray["lastname"];
As mentioned, it does not work because your object is just a list and what you are using is a object (assoc array)
.splice
The splice() method adds/removes items to/from an array, and returns the removed item(s).
Note: This method changes the original array.
delete
The delete operator removes a property from an object.
So your code should look like
delete product_variations[0]["14"]
Remember that the 14 number is a string, not a number, as you have written in your code, since that's the name of the element in your array.
Nevertheless, I highly recommend you, after having seen the code you are managing, to switch that to a list, since the keywords are only like the indices of a normal list (with the exception that they start in 1)

Count the number of object in an array in JS

"abc":[{"a":"a"},{"b":"b"},{"c":"c"}];
I got this from my ajax's data callback, how can I know there's 3 object in it? I tried .length method but it grave me the wrong number.
Using .length on the array will give you the correct answer 3, but most likely you're doing data.length which is wrong in your case.
data["abc"].length will yield correct result.
Use Below code you will get 3 in console :
<script>
var test = {"abc":[{"a":"a"},{"b":"b"},{"c":"c"}]};
console.log("Length :"+test.abc.length);
</script>
It doesnt matter if you have objects in your array or other elements, array.length always works on it.
Readup: Array.length - JavaScript | MDN
The code that you have posted, it looks like abc is a property of an object.
var obj = {
"abc":[{"a":"a"},{"b":"b"},{"c":"c"}] // semicolon removed
};
alert(obj.abc.length); // compute length/number of objects here
Array.length will give you the number of elements in the array.
Your example
([{"a":"a"},{"b":"b"},{"c":"c"}].length == 3) // => true
So your issue lies elsewhere.

Can't get JSON to output

First try at using JSON. I have an ajax/php function that returns a JSON object. Back on the js side, I can see the object and output it to a div. It looks fine. I can print it to the console, still looks good. But when I try to iterate over it and expose the individual values, I just get 'undefined' in my console. I can't figure out what I am missing. Sorry it if's something obvious, but I don't see it. Thanks!
var jsonObj = JSON.parse(xmlhttp.responseText);
console.log(jsonObj); //<--looks perfect
console.log(jsonObj.length);
document.getElementById("rightsidebox").innerHTML=response; //<--looks good
for (var group in jsonObj) {
//each of these generates 'undefined' WHY???
//I get 4 'undefined' outputs for each group, so I know that my loop is iterating correctly
console.log(group.id);
console.log(group.day);
console.log(group.time);
console.log(group.name);
}
EDIT: Here is an example of one of the JSON objects being returned by my ajax call. In this example, I only have a single object inside of the array. Of course, there will typically be multiple objects:
[{"id":"7","day":"Thursday","time":"7:00 a.m.","name":"Sub 10:00"}]
EDIT 2: Given this array, I have to ask what the point of JSON is. I can return this array without having PHP encode it in JSON format. So, if all that comes back is just a javascript array, then what have I accomplished? Why not skip the JSON encoding in PHP and then iterate over the array? Clearly there is a reason for this, so I'm obviously missing something. Is there a better way to do what I am trying to accomplish? Thanks!
Consider the following:
var myJson = '{"groupA": {"id": 123, "name": "foo"}}';
var myObj = JSON.parse(myJson);
for (var i in myObj) {
console.log(i);
console.log(i.id);
console.log(myObj[i].id);
}
The expected output here is:
myGroup
undefined
123
This is because you loop is just assigning the 'key' of your object to the value i. If you were to iterate an array, instead of an object, you'd get indices instead of strings.
In the example JSON you've given, you have an array with one object in it. If you intend to have multiple objects in your array, something like this would be better:
for (var group in jsonObj) {
var thisGroup = jsonObj[group];
thisGroup.id; // Etc etc..
}
If you have the correct jsonObj, and you say that you do, you can use formatting to output the object in an easy to read form. You don't have to loop through it.
console.log(JSON.stringify(jsonObj, null, 1));
Not sure why this works, when my original for (var group in jsonObj) loop doesn't, but whatever...
for (var i=0; i < jsonObj.length; i++) {
console.log(jsonObj[i].id);
console.log(jsonObj[i].day);
console.log(jsonObj[i].time);
console.log(jsonObj[i].name);
}

Categories

Resources