Can't access items in javascript array [duplicate] - javascript

This question already has answers here:
How can I access and process nested objects, arrays, or JSON?
(31 answers)
Closed 7 years ago.
My array is:
{
"data":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAyAAAAJYCAYAAACadoJwAAAgAElEQ…ACCCCAAAIIIICAvwIEIP760zoCCCCAAAIIIIAAAoES+P992sgQ2E6rdwAAAABJRU5ErkJggg==",
"name":"splash.png",
"imageOriginalWidth":1024,
"imageOriginalHeight":768,
"imageWidth":1969,
"imageHeight":1477,
"width":800,
"height":600,
"left":-585,
"top":-406
}
and I have two variables:
$image_data = $array['data'];
$image_name = $array['name'];
Both of these variables return undefined
Am I missing something obvious?

First off, it's important to note that this is not an array, it's an object definition.
An array can be defined as:
[
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAyAAAAJYCAYAAACadoJwAAAgAElEQ…ACCCCAAAIIIICAvwIEIP760zoCCCCAAAIIIIAAAoES+P992sgQ2E6rdwAAAABJRU5ErkJggg==",
"splash.png",
1024,
768,
1969,
1477,
800,
600,
-585,
-406
]
Which is doesn't the keys, like "data": (which can also be expressed as data:) It seems you definitely want to access values by key, so what you really want is:
var data, name, myObject;
// NOTE: We do not "quote" object keys under normal circumstances.
myObject = {
data:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAyAAAAJYCAYAAACadoJwAAAgAElEQ…ACCCCAAAIIIICAvwIEIP760zoCCCCAAAIIIIAAAoES+P992sgQ2E6rdwAAAABJRU5ErkJggg==",
name:"splash.png",
imageOriginalWidth:1024,
imageOriginalHeight:768,
imageWidth:1969,
imageHeight:1477,
width:800,
height:600,
left:-585,
top:-406
}
data = myObject["data"]; // We don't usuaully use this
name = myObject["name"]; // style, although it works.
//
// It's generally reserved for
// dynamic access.
//
// i.e. we make a string to match the keyname.
However, to be correct you should use dot syntax to access the object key.
data = myObject.data;
name = myObject.name;
I hope this has cleared things up a little for you.
On a side note DO NOT use names like $array. First don't use the $ prefix for normal variables, this isn't PHP or BASIC.
Secondly, when you have an object, you want it to be named something that is useful / meaningful / memorable. (naming things is hard!)
When you name things properly, other people can read and understand your code, and after a heavy weekend on the town, so can you.

Have you tried declaring the array and also the variables you wanna store the store the stuff from array to, using the var keyword?
E.g:
var myArray = ["hello",["world"];
By looking at your code I have the impression that you were trying to make a custom object.

Related

Cannot access nested object array with dot notation or bracket notation [duplicate]

This question already has answers here:
How can I access a JavaScript object which has spaces in the object's key?
(4 answers)
Closed 3 years ago.
I need to access an array of feature attributes that is nested inside an item list object. It looks like this.
var itemsList = {
_searchedFeatures: {
Wildlife Management Areas: [{}, {}, {}]
}
}
I need to access the Wildlife Management Areas(WMA) array and loop through it, extract an attribute value from each feature in the array and push that value to another array. The problem I am having is that I cannot access the WMA array.
I have tried using a combination of dot notation and bracket notation to get to the WMA array, but I always get undefined. I know the WMA is there and contains a list of objects because I can see them when I access the _searchFeatures object.
I have tried
itemList._searchedFeatures
which returns the array. I can see the array in the chrome console, but I need to get to the values inside or the array.
Chrome console:
Searched Features
{}
Wildlife Management Areas: (5) [c, c, c, c, c] //I need to get to this
array!
This code is not working:
itemsList._searchedFeatures["Wildlife Management Areas"];
I am expecting to see an indexed list of features that looks something like this:
0: {...}
1: {...}
2: {...}
But instead, I just get undefined. What is interesting, is when I hover the mouse over Wildlife Management Areas in the console, I am seeing what looks to be the JavaScript dot notation solution, but I don't know how to duplicate it. This is what I am seeing:
[""Wildlife Management Areas""]
I have never seen double double quotes and this will obviously not work, but I have no idea how to interpret this. Please let me know what I am not understanding.
This works:
setTimeout(function() {
var wmaArray = itemList._searchedFeatures['wildlife Management Areas'];
console.log("WMAs ", wmaArray);
}, 2000);
It's just taking a long time to get the results, so I had to extend the timeout. I know it's not the best way, I do want to set up a promise to do this, but I am still learning javascript and not very good at those yet!
You should put Wildlife Management Areas in quotes for this to work
var itemsList = {
_searchedFeatures: {
'Wildlife Management Areas': [{}, {}, {}]
}
}

JSON and reference [duplicate]

This question already has answers here:
JSON find in JavaScript
(7 answers)
Closed 7 years ago.
I receive data as a JSON object, like this:
[{"transid":1091, "payee":"McDonalds", "amount":-549},
{"transid":1092, "payee":"McDonalds", "amount":-342},
{"transid":1093, "payee":"McDonalds", "amount":371}]
I know I can access the data like this:
alert(obj[0].amount);
But I would like to be able to access the data like this:
obj[transid].amount
where transid is a previously declared and assigned variable, like this:
var transid = 1091;
alert(obj[transid].amount); //returns -549
If this is even possible, I assume the JSON object would have to be restructured (I don't have any control over how I receive the JSON object), but I don't really have any idea how to go about this. I've tried Googling and SOing, but I am just not sure what to look for.
Edit: I've looked at the proposed duplicate question as suggested by Travis J, and I do not agree that this is a duplicate. I'm not asking to loop through data. I'm asking for methods to reference by a specific index, given JSON that I don't control how it comes to me. The accepted answer in the proposed duplicate shows how I envision the code to look (in the second code box), but I don't think it really answers my question. Another answer in the proposed duplicate, posted by Hakan Bilgin, suggests using defiantjs, which would probably work. However, there are many other methods, some of which have been provided as answers to this question already.
You can use filter like
obj.filter(function(o){
return o['transid'] === 1091;
})[0].amount // -549
You can add the above function to Array's prototype like
Array.prototype.get = function(id){
return Array.prototype.filter.call(this,function(obj){
return obj['transid'] === id;
})[0].amount
}
And use it like
obj.get(1091); // -549
It is up to you to add proper validation like dealing with not found keys and duplicates.
You can create a new object from that one. Something like this
var transactionArray = [
{"transid":1091, "payee":"McDonalds", "amount":-549},
{"transid":1092, "payee":"McDonalds", "amount":-342},
{"transid":1093, "payee":"McDonalds", "amount":371}
];
var transactionsById = {};
transactionArray.forEach(function(element) {
transactionsById[element.transid] = element;
});
var transid = 1091;
alert(transactionsById[transid].amount); //returns -549
Where transactionArray is what you refer to as obj in your question.

What is a good way to create a JavaScript array with big indices?

I'm making a web app where a user gets data from PHP, and the data consists of MySQL rows, so I want to save the used ones in a global variable, something like a buffer, to prevent extra AJAX requests.
I'm doing this right now :
window.ray = []; // global variable
$(function(){
data = getDataWithAjax(idToSearch);
window.ray[data.id] = data.text;
});
but when the id is big, say 10 for now, window.ray becomes this :
,,,,,,,,42
so it contains 9 unnecessary spots. Or does it? Is it only visible when I'm doing console.log(window.ray);
If this is inefficient, I want to find a way like PHP, where I can assign only indices that I want, like :
$array['420'] = "abc";
$array['999'] = "xyz";
Is my current way as efficient as PHP, or does it actually contain unnecessary memory spots?
Thanks for any help !
Use an object instead of an array. The object will let you use the id as the key and be more efficient for non-sequential id values.
window.ray = {}; // global variable
$(function(){
data = getDataWithAjax(idToSearch);
window.ray[data.id] = data.text;
});
You can then access any element by the id:
var text = window.ray[myId];
If you are assigning values directly by property name, then it doesn't make any difference in terms of performance whether you use an Array or an Object. The property names of Arrays are strings, just like Objects.
In the following:
var a = [];
a[1000] = 'foo';
then a is (a reference to) an array with length 1,001 (always at least one greater than the highest index) but it only has one numeric member, the one called '1000', there aren't 1,000 other empty members, e.g.:
a.hasOwnProperty['999']; // false
Arrays are just Objects with a special, self–adjusting length property and some mostly generic methods that can be applied to any suitable object.
One feature of sparse arrays (i.e. where the numeric properties from 0 to length aren't contiguous) is that a for loop will loop over every value, including the missing ones. That can be avoided and significant performance gains realised by using a for..in loop and using a hasOwnProperty test, just like an Object.
But if you aren't going to use any of the special features of an Array, you might as well just use an Object as suggested by jfriend00.

Joining values in an Javascript array

Say I have:
var Certificated = {}
Sub items are added dynamically and variate. Possible outcome:
var Certificated = {
Elementary: ["foo","bar", "ball"]
MiddleSchool: ["bar", "crampapydime"]
};
I want to do the following:
Certificated.Elementary = Certificated.Elementary.join("");
Except I need it to do that on all of the objects inside.
Keep in mind I can't know for sure the titles of nor how many objects will be inside Certificated.
My question is how can I use .join("") on all elements inside Certificated, without calling each one specifically?
EDIT: I am aware .join() is for arrays and the objects inside Certificated are going to be arrays. Therefore the join method.
Does this work?
for (var key in Certificated) {
if (Certificated.hasOwnProperty(key)) {
Certificated[key] = Certificated[key].join("");
}
}
It loops through all properties of Certificated, and makes a quick safe check for the key being a real property, then uses bracket notation - [""] - to do your join.
Quick question - are you sure you want to use join? I know you just provided an example, but you can't call join on a string...it's for arrays. Just wanted to make sure you knew.
Here's a jsFiddle of my code working with arrays being used for the properties:
http://jsfiddle.net/v48dL/
Notice in the browser console, the properties' values are strings because the join combined them with "".

Deserializing JavaScript object instance

I am working on an app that heavily uses JavaScript. I am attempting to include some object-oriented practices. In this attempt, I have created a basic class like such:
function Item() { this.init(); }
Item.prototype = {
init: function () {
this.data = {
id: 0,
name: "",
description: ""
}
},
save: function() {
alert("Saving...");
$.ajax({
url: getUrl(),
type: "POST",
data: JSON.stringify(this.data),
contentType: "application/json"
});
}
}
I am creating Item instances in my app and then saving them to local storage like such:
Item item = new Item();
window.localStorage.setItem("itemKey", JSON.stringify(item));
On another page, or at another time, I am retriving that item from local storage like such:
var item = window.localStorage.getItem("itemKey");
item = JSON.parse(item);
item.save();
Unfortunately, the "save" function does not seem to get reached. In the console window, there is an error that says:
*save_Click
(anonymous function)
onclick*
I have a hunch that the "(anonymous function)" is the console window's way of saying "calling item.save(), but item is an anonymous type, so I am trying to access an anonymous function". My problem is, I'm not sure how to convert "var item" into an Item class instance again. Can someone please show me?
Short answer:
Functions cannot be serialized into JSON.
Explanation:
JSON is a cross-platform serialization scheme based on a subset of JS literal syntax. This being the case, it can only store certain things. Per http://www.json.org/ :
Objects: An object is an unordered set of name/value pairs. An object begins with { (left brace) and ends with } (right brace). Each name is followed by : (colon) and the name/value pairs are separated by , (comma).
Arrays: An array is an ordered collection of values. An array begins with [ (left bracket) and ends with ] (right bracket). Values are separated by , (comma).
values: A value can be a string in double quotes, or a number, or true or false or null, or an object or an array. These structures can be nested.
Functions cannot be serialized into JSON because another non-JS platform would not be able to unserialize and use it. Consider the example in reverse. Say I had a PHP object at my server which contained properties and methods. If I serialized that object with PHP's json_encode() and methods were included in the output, how would my JavaScript ever be able to parse and understand PHP code in the methods, let alone use those methods?
What you are seeing in your resulting JSON is the toString() value of the function on the platform you're using. The JSON serilizer calls toString() on anything being serialized which isn't proper for JSON.
I believe your solution is to stop storing instances in JSON/local storage. Rather, save pertinent data for an instance which you set back to a new instance when you need.
I know this question is answered already, however I stumbled upon this by accident and wanted to share a solution to this problem, if anyone is interested.
instead of doing this:
var item = window.localStorage.getItem("itemKey");
item = JSON.parse(item);
item.save();
do something like this:
// get serialized JSON
var itemData = window.localStorage.getItem("itemKey");
//instantiate new Item object
var item = new Item();
// extend item with data
$.extend(item, JSON.parse(itemData));
// this should now work
item.save();
this will work so long as the function you are wanting to call (ie, save()) is prototypal and not an instance method (often times the case, and is indeed the case in the OP's original question.
the $.extend method is a utility method of jquery, but it is trivial to roll your own.
You cant do that, how can javascript possibly knows that item have a save function ? json doesnt allow functions as datas. just read the json spec , you cant save functions.
what you need to do is to create a serialize and deserialize method in the hash you want to stock. that will specifiy what to export and how you can "wake up" an object after parsing the corresponding json string.
You can only store plain Objects in DOMstorages (cookies, urlparams..., everything that needs [de]serialisation through JSON.stringify/JSON.parse). So what you did when sending the ajax data
ajaxsend(this.data);
also applies to string serialisation. You can only store the data, not the instance attributes (like prototype, constructor etc.). So use
savestring(JSON.stringify(item.data));
which is possible because item.data is such a plain Object. And when restoring it, you will only get that plain data Object back. In your case it's easy to reconstruct a Item instance from plain data, because your Items hold their values (only) in a public available property:
var item = new Item;
item.data = JSON.parse(getjsonstring());
Disclaimer
Not a full time time J.S. Developer, answer may have some minor bugs:
Long Boring Explanation
As mentioned by #JAAulde, your object cannot be serialized into JSON, because has functions, the technique that you are using doesn't allow it.
Many people forget or ignore that the objects that are used in an application, may not be exactly the same as saved / restored from storage.
Short & quick Answer
Since you already encapsulate the data members of your object into a single field,
you may want to try something like this:
// create J.S. object from prototype
Item item = new Item();
// assign values as you app. logic requires
item.data.name = "John Doe";
item.data.description = "Cool developer, office ladies, love him";
// encoded item into a JSON style string, not stored yet
var encodedItem = JSON.stringify(item.data)
// store string as a JSON string
window.localStorage.setItem("itemKey", encodedItem);
// do several stuff
// recover item from storage as JSON encoded string
var encodedItem = window.localStorage.getItem("itemKey");
// transform into J.S. object
item.data = JSON.parse(encodedItem);
// do other stuff
Cheers.

Categories

Resources