OO JS - loop through object array - javascript

Quite new to OO Js, used to program with function after function so trying to fix that now!
I'm making a tab layout -
I create a tab by calling: tab.NewTab();
I can access the tabs at tab[0], tab[1] etc
var tabCount = 0;
var tabs = [];
tabs.NewTab = function (){
var tabName = "tab" + tabCount;
tabs[tabCount] = new Tab(tabName);
tabCount++;
};
function Tab(tabName){
return{
name: tabName
}
}
I wanted to make a function that counts how many tabs are open:
tabs.HowMany = function () {
for (var i in tabs) {
alert("new");
}
};
This is returning the methods too (0,1, NewTab, HowMany).
Any advice?

You're looking for tabs.push(new Tab(tabName));
Then ditch tabCount, and instead use the length property native to all javascript arrays: tabs.length
Also, your Tab constructor is wrong. As it is currently written it should not be called with new. Just call Tab('someName') and it will return to you the object you're looking for. If you do that however, change it to tab since non-constructor functions should be lowercase.
If you're really eager to use the new keyword, this is what Tab should look like:
function Tab(tabName){
this.name = tabName;
}
EDIT
If you want to iterate over all members of your array, this is the simplest way:
for (var i = 0; i < tabs.length; i++)
var currentTab = tabs[i];

You need to change var tabs = []; to var tabs = new Array();.
And add items to it using tabs.push(new Tab(tabName));
Simple count:
var count = tabs.lenght
Enumeration of items:
for (var i = 0; i < tabs.length; i++) {
alert(tabs[i]);
}

You could do:
tabs.HowMany = function () {
for (var i in tabs) {
if(tabs.hasOwnProperty(i)){
if(typeof tabs[i] !== 'function'){
alert('new')
}
}
}
};
but you'd better switch using it as array
tabs.push(new Tab(tabName))
tabs.HowMany = function () {
return tabs.length
};

Related

Can't loop through my Array and return a new Array

I'm trying to loop through var algos , add it to the end of the URL, then have it return the new array urllist. I keep getting an empty an empty array. I don't get any errors thrown so it makes me think its a scope issue.
Here is my code:
var algos = ["SCRYPT","X11","DAGGERHASIMOTO" ];
let urllist = new Array();
// creates the url list
function buildlist ()
{
for (let i=0; i < algos.length; i++){
let urllink = 'https://api2.nicehash.com/main/api/v2/public/algo/history?algorithm='+algos[i];
urllist.push(urllink);
};
return urllist
};
console.log(urllist);
In my understanding of Js, function buildlist should have access to the global variable let urllist= new Array();
It's probably something small I'm overlooking. I've seen other answers on SO and I believe my for loop and function is written properly.
Thanks fellow SO hackers.
Prefer pure functions for better code quality. The pure function should return something that was calculated by its arguments only. Avoid using global vars when you can avoid these.
function buildlist (incomingArray)
{
let urllist = new Array();
for (let i=0; i < incomingArray.length; i++) {
urllist.push('https://api2.nicehash.com/main/api/v2/public/algo/history?algorithm='+incomingArray[i]);
};
return urllist;
};
console.log( buildlist(["SCRYPT","X11","DAGGERHASIMOTO"]) );
You are declaring the function but you didn't invoke it;
try adding buildlist() just before the console.log
So this is how the solution should look:
var algos = ["SCRYPT","X11","DAGGERHASIMOTO" ];
function buildlist (incomingArray)
{
let urllist = new Array();
for (let i=0; i < incomingArray.length; i++) {
urllist.push('https://api2.nicehash.com/main/api/v2/public/algo/history?algorithm='+incomingArray[i]);
};
return urllist;
};
// prints the list to the console
console.log( buildlist(algos) );

Use closure inside array with pure javascript

I need to copy a string inside an array to a value inside another array that is created in a loop. In the end when I print all names are the last in the array of names. I want to copy/clone the value so that I don't have a reference and I would like it to be only in native javascript without external libraries.
This is my code
var exp_names =["name1","name2","name3"];
var i;
for (i = 0; i < exp_names.length; i++) {
d3.tsv("data/"+exp_names[i], function(data) {
data.forEach(function(d){
//Do stuff with my tsv
d.expId = exp_names[i];
});
});
});
And then all expId are "name3"
Data is loading correctly per file.
I have tried with jquery's extend function and also lodash's clone function, I have tried my own clone function and nothing works it will still throw "name3" for all the expId.
These didn't work:
var newname = new String(exp_names[i]);
var newname = $.extend(true, {}, exp_names[i]);
var newname = $.extend( {}, exp_names[i]);
var newname = _.clone(exp_names[i]);
var newname = exp_names[i].slice(0);
I am desperate by now.
You need to use bind function.
var exp_names =["name1","name2","name3"];
var i;
var func = [];
for (i = 0; i < exp_names.length; i++) {
func[i]=(function(index){
d3.tsv("data/"+exp_names[index], function(data) {
data.forEach(function(d){
//Do stuff with my tsv
d.expId = exp_names[index];
});
});
}).bind(this,i);
}
for(i = 0; i < 3; i++){
func[i](i);
}
Another solution is to use let keyword.
ES6 provides the let keyword for this exact circumstance. Instead of using closures, we can just use let to set a loop scope variable.
Please try this:
for (let i = 0; i < exp_names.length; i++) {
d3.tsv("data/"+exp_names[i], function(data) {
data.forEach(function(d){
//Do stuff with my tsv
d.expId = exp_names[i];
});
});
}
I guess usage of IIFE and bind together, in the first answer is a little weird. It's best to choose either one of them. Since in the newest versions of the browsers bind is way faster than an IIFE closure and the let keyword I might suggest you the bind way.
A similar example to your case might be as folows;
var exp_names = ["name1","name2","name3"],
lib = {doStg: function(d,cb){
cb(d);
}
},
data = [{a:1},{a:2},{a:3}];
for (i = 0; i < exp_names.length; i++) {
lib.doStg(data, function(i,d) {
d.forEach(function(e){
//Do stuff with doStg
e.expId = exp_names[i];
console.log(e);
});
}.bind(null,i));
}

Passing through array that is in an object into a function

I want to pass an object into a function as a parameter, and assign things to properties of that object, then those would be accessible outside of the function. But I am not to clear on how it is done.
At first I thought it could be done using callbacks, but it was made clear to me that JavaScript does not work that way. I eventually managed to get it working, and the undefined error messages went way. But I wanted to now pass an array through the function. How can this be done? This is what I've done so far, but it doesn't seem to be working.
var journey = {};
journey['waypointsArrayItem'] = new Array();
setupAddress(journey)
function setupAddress(journey) {
var waypointsItem = $('.timeline-item.active-item > .timeline-status > .waypoints').text().substring(4);
journey.waypointsArrayItem = [];
journey.waypointsArrayItem = listToArray(waypointsItem, ', ');
for (var i = 0; i < waypointsArray.length; i++) {
journey.waypointsArrayItem[i] = journey.waypointsArrayItem[i];
}
}
You are copying array items to themselves. Copy from the waypointsArray array to the journey.waypointsArrayItem array:
function setupAddress(journey) {
var waypointsItem = $('.timeline-item.active-item > .timeline-status > .waypoints').text().substring(4);
var waypointsArray = listToArray(waypointsItem, ', ');
for (var i = 0; i < waypointsArray.length; i++) {
journey.waypointsArrayItem[i] = waypointsArray[i];
}
}
Depending on what you need, you could also just replace the entire array:
function setupAddress(journey) {
var waypointsItem = $('.timeline-item.active-item > .timeline-status > .waypoints').text().substring(4);
journey.waypointsArrayItem = listToArray(waypointsItem, ', ')
}
Assigning properties to an object in a function is the same as assigning properties outside of a function.
function addName(obj, name) {
obj.name = name;
}
var bob = {};
console.log(bob.name); // undefined
addName(bob, 'Bob');
console.log(bob.name); // 'Bob'

jQuery how to acess a function within a plugin?

So I am trying to access a function within a plugin but am not sure how to.
Here is a snippet of code. I am trying to access the find_matches function OUTSIDE of this plugin and get a return from it.
$.fn.variation = function () {
$.fn.variation.find_matches = function( variations, settings ) {
var matching = [];
for (var i = 0; i < variations.length; i++) {
var variation = variations[i];
matching.push(variation);
}
return matching;
}
};
Thanks for looking.
If you do not want to expose the function to external scope as a utility function then you can write it as a closure function
$.fn.variation = function () {
var find_matches = function( variations, settings ) {
var matching = [];
for (var i = 0; i < variations.length; i++) {
var variation = variations[i];
matching.push(variation);
}
return matching;
}
var matches = find_matches(variations, settngs);//you can call it directly
};
If you want to expose the function to external context then you can use the format used by you and you can access it using
var matches = $.fn.variation.find_matches(variations, settngs);

Update happens only on the last row, instead of first

function createTextFields(obj) {
for (var i = 0; i < obj.length; i++) {
var dataDump = {};
for (var key in obj[i]) {
var textField = Ti.UI.createTextField(pm.combine($$.labelBrown, {
left: 200,
height:35,
value:obj[i][key],
width:550,
keyboardType:Ti.UI.KEYBOARD_NUMBER_PAD,
layout:'horizontal',
backgroundColor:'transparent',
id:i
}));
dataDump[key] = textField.value;
var callback = function (vbKey) {
return function (e) {
dataDump[vbKey] = e.source.value;
};
}(key);
}
globalData.push(dataDump);
}
}
I am using the simlar code for Adding the data and it works fine. I posted the problem yesterday and it got resolved...
Last Object is always getting updated?
Now when i go to edit page, it shows me four text fields or number of text fields added... now when i edit something and click on save... the value get's updated on the fourth or the last TextFields Object...
Don't define functions inside loops. Computationally expensive and leads to problems, like this one. Here's a fix that should solve it:
function createTextFields(obj) {
var callback = function (vbKey, localDump) {
return function (e) {
localDump[vbKey] = e.source.value;
};
}
var i;
var max = obj.length;
for (i = 0; i < max; i++) {
var dataDump = {};
for (var key in obj[i]) {
dataDump[key] = textField.value;
var callBackInstance = function(keyn, dataDump);
}
globalData.push(dataDump);
}
}
JavaScript does not have block level scope, so your variables dataDump and callback, though "declared" inside for-loops actually belong to the function. As in, you're saving a value to dataDump, then you're overwriting it, each time you go through the loop. Which is why finally only the code that operated on the last value remains.
Take a look at What is the scope of variables in JavaScript? too.

Categories

Resources