accessing methods of an object within an array - javascript

I have an array which I'm adding objects to dynamically like so
var _plugins = [];
this.registerPlugin = function(plugin){
_plugins.push(plugin);
plugin.onInit()
},
This is all within a class and I am trying to use a method like this which should run the method passed in to meth
this.runPluginMethod = function(meth, call_obj){
for (x in _plugins){
x[meth](call_obj)
}
}
The Objects I am adding to the _plugins array are created like this
var ourPlugin = Object.create(babblevoicePlugin);
Object.defineProperty(ourPlugin, 'onInit', {value : function()
{
console.log('this is from reflex oninit')
}});
When I try running mianClass.runPluginMethod('onInit', 'a') It does nothing, doesn't run console.log like it should to my mind.
Can anyone help? am I doing something wrong? is this possible?

I think the problem is here:
this.runPluginMethod = function(meth, call_obj){
for (x in _plugins){
x[meth](call_obj)
}
}
You're trying to access a property of a key instead of the object you're looking for. Changing it to the following should work.
this.runPluginMethod = function(meth, call_obj){
for (x in _plugins){
_plugins[x][meth](call_obj)
}
}
EDIT
As another example, check the output of the following in a js console:
x = ['a','b','c'];
for (i in x){ console.log(i, x[i]) };

Related

What is the difference between these 2 ways of creating a list of arrays in JavaScript?

How do I dynamically create a list of arrays in JavaScript, that actually shows up in the Developer console as a list of arrays?
Just rephrased this question; there are plenty of examples how to do this, and my code is working, but I'm getting 2 very different results from these 2 methods:
I tried this:
var volume = [];
for (i = 0; i < json.length; i++) {
var item = new Array(2);
item[0] = json[i].json_date;
item[1] = json[i].volume;
volume.push(item);
}
So, this code works, and seems to create an array of arrays, but in the developer console the result of console.log(typeof volume[0]) is undefined.
If I create the array manually, it works much better:
var volume = [
[1313964000000,23.17],
[1314050400000,23.78],
[1314741600000,25.24],
[1314828000000,24.77],
[1440021600000,82.69]
];
Now console.log(typeof volume[0]) is object. And console.log(volume) results in: (5) [Array(2), Array(2), Array(2), Array(2), Array(2)]. That's what I need, not just [].
I've spent the entire day searching for answers, and have tried many variations of this code, but can't seem to find code that will dynamically create that volume array to correctly show up as an array of arrays.
Has anyone else run into this?
Here is the full code:
var volume = [];
fetch("http://localhost:3000/api/v1/TSLA").then(function(response) {
if(response.ok) {
response.json().then(function(json) {
for (i = 0; i < Object.keys(json).length; i++){
volume.push(new Array(json[i].json_date, json[i].volume));
}
});
} else {
console.log('Network request failed with response ' +
response.status + ': ' + response.statusText);
}
});
console.log(volume);
So, the answer from oknawe helped me to solve this problem; however in a way the question has still not been answered, because the volume array is only usable inside that fetch function. Later in the code, the data is still there, but individual elements test as undefined...
That should work fine, assuming the variable json is structured as you expect. You can also try:
let volume = json.map((i) => [i.json_date, i.volume]);
(Provided your environment lets you use ES6.)
Instead of manually looping over the array, you can iterate over the contents of the array with the map function.
The length of a JSON object will be undefined since objects do not have a length value. You can use Object.keys to get size but that won't do you much good since object values cannot be accessed by index:
var volume = [];
for (i = 0; i < Object.keys(json).length; i++) {
// can't access using json[i] here
}
However, you can use Object.keys(json) or Object.values(json)
and do something like below:
(you'll need to have code inside the json callback)
let volume = [];
fetch('/api/foo/bar').then((data) => {
return data.json();
}).then((json) => {
console.log(json);
Object.keys(json).forEach((obj) => {
// obj = {"json_date": 1313964000000, "volume": 23.17, ...}
console.log(obj);
volume.push(new Array(obj["json_date"], obj["volume"]));
});
console.log(volume);
}).catch((e) => {
console.error('There was a problem with the request');
})
Thanks to oknawe, I got it working. Using that code works, provided I use that volume array inside the fetch code. Outside that, the volume array still contains data, but individual elements are undefined. Many thanks to everyone who posted here!

how to handle JSON.stringify when string is empty

I'm trying to handle an object which doesn't exist in the array.
var departureGate = JSON.stringify(data.flightStatuses[i].airportResources.departureGate);
So, when the javascript code gets here, it fall over because there happens to be nothing in the actual string it is trying to parse. I've tried catching it with "typeof", but that doesn't work either. I'm stumped.
So, the data.flightStatuses[i] array exists, just not the .airportResources.departureGate.
I tried to see if it exists using "typeof data.flightStatuses[i].airportResources.departureGate". It still falls over.
alert (typeof data.flightStatuses[i]) // this comes back "object"
alert (typeof data.flightStatuses[i].airportResources.departureGate) // it dies...
Should be fairly straight forward like this:
if (data.flightStatuses[i].airportResources.departureGate) {
var departureGate = JSON.stringify(data.flightStatuses[i].airportResources.departureGate);
}
It looks like your problem is with airportResources, and not with departureGate.
Try this:
var departureGate = null,
ar = data.flightStatuses[i].airportResources;
if(ar && 'departureGate' in ar){
departureGate = JSON.stringify(ar.departureGate);
}
Cheers
You can check if the departuregate is defined as a property at all like this, and then do the action you wanted, for example:
if(data.flightStatuses[i].airportResources.hasOwnProperty('departureGate') {
var departureGate = JSON.stringify(data.flightStatuses[i].airportResources.departureGate);
} else {
var departuregate = null; // for example
}
More info here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty

javascript JSON access

I have a JSON object that goes somewhat like this:
var waitingGames = {
arithemetic:[
{
games:[]
},
{
games:[]
},
{
games:[]
}
]
and so on for synonyms, antonyms and translation. My problem is that I can't seem to access the games array by using this:
var gametype = url_parts.query.type;
var gamesize = url_parts.query.size;
if(games.waitingGames.gametype[gamesize].games.length == 0)
I get that gametype is undefined, even though I already tried printing the variable and it has the right value (arithemetic in the above example). Any ideas how to fix this?
Please try
if(games.waitingGames.arithemetic[gamesize].games.length == 0)
Use:
games.waitingGames[gametype][gamesize].games.length
Here you are using gametype as a variable like you meant to.
See this proof-of-concept JSFiddle demo.
You can access the value from inner games object using this expresson
console.log(waitingGames.arithemetic[0].games);
Use a for loop to loop through arithemetic array.
for(var i =0, j = waitingGames.arithemetic.length; i<j; i++){
if(waitingGames.arithemetic.games.length == 0){
}
}
Fixed, had to use the brackets to change use the variable content to reach where i wanted inside the JSON object, thanks all

Can I loop through 2 objects at the same time in JavaScript?

related (sort of) to this question. I have written a script that will loop through an object to search for a certain string in the referring URL. The object is as follows:
var searchProviders = {
"google": "google.com",
"bing": "bing.com",
"msn": "search.msn",
"yahoo": "yahoo.co",
"mywebsearch": "mywebsearch.com",
"aol": "search.aol.co",
"baidu": "baidu.co",
"yandex": "yandex.com"
};
The for..in loop I have used to loop through this is:
for (var mc_u20 in mc_searchProviders && mc_socialNetworks) {
if(!mc_searchProviders.hasOwnProperty(mc_u20)) {continue;}
var mc_URL = mc_searchProviders[mc_u20];
if (mc_refURL.search(mc_URL) != -1) {
mc_trackerReport(mc_u20);
return false;
}
Now I have another object let's call it socialNetworks which has the following construct:
var socialNetworks = {"facebook" : "facebook.co" }
My question is, can I loop through both of these objects using just one function? the reason I ask is the variable mc_u20 you can see is passed back to the mc_trackerReport function and what I need is for the mc_u20 to either pass back a value from the searchProviders object or from the socialNetworks object. Is there a way that I can do this?
EDIT: Apologies as this wasn't explained properly. What I am trying to do is, search the referring URL for a string contained within either of the 2 objects. So for example I'm doing something like:
var mc_refURL = document.referrer +'';
And then searching mc_refURL for one of the keys in the object, e.g. "google.com", "bing.com" etc. 9this currently works (for just one object). The resulting key is then passed to another function. What I need to do is search through the second object too and return that value. Am I just overcomplicating things?
If I understand your question correctly, you have a variable mc_refURL which contains some URL. You want to search through both searchProviders and socialNetworks to see if that URL exists as a value in either object, and if it does you want to call the mc_trackerReport() function with the property name that goes with that URL.
E.g., for mc_refURL === "yahoo.co" you want to call mc_trackerReport("yahoo"), and for mc_ref_URL === "facebook.co" you want to call mc_trackerReport("facebook").
You don't say what to do if the same URL appears in both objects, so I'll assume you want to use whichever is found first.
I wouldn't create a single merged object with all the properties, because that would lose information if the same property name appeared in both original objects with a different URL in each object such as in an example like a searchProvider item "google" : "google.co" and a socialNetworks item "google" : "plus.google.com".
Instead I'd suggest making an array that contains both objects. Loop through that array and at each iteration run your original loop. Something like this:
var urlLists = [
mc_searchProviders,
mc_socialNetworks
],
i,
mc_u20;
for (i = 0; i < urlLists.length; i++) {
for (mc_u20 in urlLists[i]) {
if(!urlLists[i].hasOwnProperty(mc_u20))
continue;
if (mc_refURL.search(urlLists[i][mc_u20]) != -1) {
mc_trackerReport(mc_u20);
return false;
}
}
}
The array of objects approach is efficient, with no copying properties around or anything, and also if you later add another list of URLs, say programmingForums or something you simply add that to the end of the array.
You could combine the two objects into one before your loop. There's several approaches here:
How can I merge properties of two JavaScript objects dynamically?
var everything = searchProviders;
for (var attrname in socialNetworks) { everything[attrname] = socialNetworks[attrname]; }
for(var mc_u20 in everything) {
// ...
}
for (var i = 0; i < mc_searchProviders.length; i++) {
var searchProvider = mc_searchProviders[i];
var socialNetwork = mc_socialNetworks[i];
if (socialNetwork != undefined) {
// Code.
}
}
Or am i horribly misunderstanding something?

javascript - coldfusion - working with a list

This is probably easy for someone.
I am returning a list of campaignIDs (12,45,66) via JSON to a javascript variable
var campaignList = res.DATA.CAMPAIGNS
Now, given a specified campaignID passed in the URL
var campaignId ='<cfoutput>#url.campaignID#</cfoutput>'
I want to check if the returned list contains this campaignID
Any help much appreciated.
Plenty of ways to do it, but I like nice data structures, so ...
Split the list on comma, then loop over list, looking for value:
function campaignExists(campaignList,campaignId) {
aCampaignList = campaignList.split(',');
for (i=0;i<aCampaignList.length;i++) {
if (aCampaignList[i]==campaignId)
return true;
}
return false;
}
Since Array.indexOf sadly isn't cross browser, you're looking at something like:
// assume there is no match
var match_found = false;
// iterate over the campaign list looking for a match,
// set "match_found" to true if we find one
for (var i = 0; i < campaignList.length; i += 1) {
if (parseInt(campaignList[i]) === parseInt(campaignId)) {
match_found = true;
break;
}
}
If you need to do this repeatedly, wrap it in a function
Here's a bit of a "out of the box" solution. You could create a struct for your property id's that you pass into the json searilizer have the key and the value the same. Then you can test the struct for hasOwnProperty. For example:
var campaignIDs = {12 : 12, 45 : 45, 66 : 66};
campaignIDs.hasOwnProperty("12"); //true
campaignIDs.hasOwnProperty("32"); //false
This way if the list is pretty long you wont have to loop through all of the potential properties to find a match. Here's a fiddle to see it in action:
http://jsfiddle.net/bittersweetryan/NeLfk/
I don't like Billy's answer to this, variables within the function have been declared in the global scope and it is somewhat over complicated. If you have a list of ids as a string in your js just search for the id you have from user input.
var patt = new RegExp("(^|,)" + campaignId + "(,|$)");
var foundCampaign = campaignList.search(patt) != -1;

Categories