inovke functions javascript using while - javascript

can anyone tell me what is wrong here im just try to invoke this list of functions using array and while if it's possible thanks in advance.
var funciones = ["basicas();", "likeFbk();", "cambiarFondo();"],
i = 0;
while (funciones[i]) {
funciones[i];
i++;
}
jslint show this errors:
91 Expected an assignment or function call and instead saw an expression. funciones[i];
92 Unexpected '++'.
Solved, I use "i += 1;" instead of "i++;" and update the list of functions treated as a string, here is the code:
var funciones = [basicas, likeFbk, cambiarFondo], i = 0;
while (funciones[i]) {
funciones[i]();
i += 1;
}
thank's guys!

try it this way (not sure what you intend to do though, i am guessing you want to iterate unless there is no value at ith index)
var funciones = [basicas, likeFbk, cambiarFondo], i = 0;
while (funciones[i])
{
funciones[i]();
i++;
}

You can't invoke functions like that. The functions array is just a list of strings and not a list of functions. You have two ways of doing this:
Instead of list of strings, use list of functions as below:
var functions = [basicas, likeFbk, cambiarFondo];
while (i in funciones) {
functions[i]();
}
Use eval to evaluate string that contains javascript executable code:
var funciones = ["basicas();", "likeFbk();", "cambiarFondo();"],
i = 0;
while (funciones[i]) {
eval(funciones[i]);
i++;
}
Always go for the first approach, because the second approach is considered as evil.

Or if you prefer
var call = Function.call;
[basicas, likeFbk, cambiarFondo].forEach(call, call);
How this works is left as an exercise.

Related

JavaScript combining function parameter with excisting variable

I am creating a piece of code that repeats for multiple variables and I was wondering if it might be easier to make a function for it, and in the function 'dynamically' adjust the variable that I need to change.
Example: I am creating 31 doors that are either open or closed. So I have:
var door1State = 0;
var door2State = 0;
...
var door31State = 0;
My question is wether it's possible to create a function where I pass the door number as a parameter, like this:
function openDoor(doorNumber) {
door+doorNumber+State = 1;
}
So when I bind a listener to the door, I don't have to write anonymous functions everytime.
I hope my explanation is clear, if not I'm happy to clarify it a bit more.
Thanks in advance!
EDIT: Thanks for all the helpfull replies, I have a next question regarding this issue. I am working with 'Blippar', and they have an API which works fairly easy, but now I need to animate the doors to open. First I've declared the 'sprites' in the 'scene', and next I need to animate the specific parts
deur1.onTouchEnd = function() {
if (door1Openable == 1) {
deur1.animate().rotationY(180).scale(600,360).translation(0,0,95).duration(1000);
deur1text.animate().rotationY(0).scale(600,360).translation(0,0,100).duration(1000);
setTimeout(function(){
door1State = 1;
}, 1500);
} else {
return false;
}
This happens 31 times, for 31 doors. My question is, how would it be easiest to covert this into a function with parameters? The only required parameters are 'door number', 'x position' and 'y position'.
I tried something like this, which obviously didn't work, but I'm having a hard time finding the correct way to do it.
function() openDoor(doorNumber,xPos,yPos) {
if ('door'+doorNumber+'Openable' == 1) {
'deur'+doorNumber.animate().rotationY(180).scale(600,360).translation(xPos,yPos,95).duration(1000);
'deur'+doorNumber+'text'.animate().rotationY(0).scale(600,360).translation(xPos,yPos,100).duration(1000);
setTimeout(function(){
'door'+doorNumber+'Openable' = 1;
}, 1500);
} else {
return false;
}
Again, hopefully it's clear enough, I am basically trying to dynamically use variables within a function by using parameters.
EDIT 2: The API doesn't accept window[] for some reason, it runs in-app.
Try using an array that holds your state
const Doors=[
{
id:1,
isOpen:true,
},
{
id:2,
isOpen:true,
},
{
id:3,
isOpen:false,
}
//..etc
]
this is much easier to handle and manipulate than a huge number of variables.
To open the door you can do something like this :
const OpenDoor=(doorNumber)=>{
Doors.forEach(function(door, index) {
if(door.id===doorNumber)
Doors[index].isOpen = true;
});
}
and then OpenDoor(3);
It's possible, if you change the door#State variables to a single object instead of 31 separate variables. Then, you can just use bracket notation to look up the correct object.:
const doorStates = { door1State: 0, door2State: 0, ... };
function openDoor(doorNumber) {
doorStates['door' + doorNumber + 'state'] = 1;
}
Or, you might consider using an array instead:
// Create an array of length 31, all elements are 0:
const doorStates = Array.from({ length: 31 }, () => 0);
function openDoor(doorNumber) {
// arrays are zero-indexed
doorStates[doorNumber - 1] = 1;
}
You could try to make a dictionary of the doors.
It seems like your usage might merit the use of a dictionary instead of multiple variables.
Here's an example:
list_dict = {};
function(doorname)
{
this.list_dict[doorname] = 0;
}
You might also want to read a bit about maps, here: Javascript Maps
Yes, it's possible.
function openDoor(number) {
window['door'+number+'State'] = 1;
}
for (var i = 1; i <= 31; i++) {
window['door'+i+'State'] = 0;
}
openDoor(2)
console.log(door2State)
You can also use an array for that:
var doors = [
0,0,0,0,0,0,...0 // to 31 0s
];
Then reference door1State using doors[0]

Why does the For Loop not work when I run it?

I'm trying to get this for loop to run correctly but it is just not. The objects inside of the loop don't run and I don't understand why.
for (i = 0; i < 26; i++) {
wordFound = Math.floor(Math.Random());
document.write(wordFound);
wordData = [wordFound];
if (wordFound != wordFound.indexOf(wordData)) {
document.write('Words being generated...');
} else {
document.write('Words being generated...');
}
}
Math.Random() is not a function, should be Math.random().
Also wordFound is not a string or array so you can't use indexOf().
NOTE : Math.floor(Math.random()) will always return O.
Hope this helps.
wordMeta.indexOf(wordFound))
Array has method indexOf ,if u want get the position of wordMeta in work Found,you should use method like this code what I had write.

Simplifying a javascript function with repeated similar lines (with a loop?)

Okay, I hope you don't all facepalm when you see this - I'm still finding my way around javascript.
I am putting together an RSVP form for a wedding website.
I want the guests to be able to add their names to the RSVP form, but only have as many fields showing as required. To this end, after each name field, there is a link to click, which will, when clicked, show a name field for the next guest.
The code below works... but I am sure it can be tidier.
I have tried to insert a for() loop into the code in several different ways, I can see that the for() loop increments correctly to the last value - but when it does so, it leaves only the last addEventListener in place. I can only assume, that I should be using a different kind of loop - or a different approach entirely.
How should I tidy up the following?
<script>
function showNextGuest(i) {
document.getElementsByTagName(\'fieldset\')[i].style.display = \'block\';
}
function initiateShowNextGuest() {
document.getElementsByTagName('fieldset')[0].getElementsByTagName('a')[0].addEventListener('click',function(){showNextGuest(1);},false);
document.getElementsByTagName('fieldset')[1].getElementsByTagName('a')[0].addEventListener('click',function(){showNextGuest(2);},false);
document.getElementsByTagName('fieldset')[2].getElementsByTagName('a')[0].addEventListener('click',function(){showNextGuest(3);},false);
document.getElementsByTagName('fieldset')[3].getElementsByTagName('a')[0].addEventListener('click',function(){showNextGuest(4);},false);
document.getElementsByTagName('fieldset')[4].getElementsByTagName('a')[0].addEventListener('click',function(){showNextGuest(5);},false);
}
window.onload = initiateShowNextGuest();
</script>
Your intuition is right - a for loop could indeed simplify it and so could a query selector:
var fieldsSet = document.querySelectorAll("fieldset"); // get all the field sets
var fieldss = [].slice.call(asSet); // convert the html selection to a JS array.
fields.map(function(field){
return field.querySelector("a"); // get the first link for the field
}).forEach(function(link, i){
// bind the event with the right index.
link.addEventListener("click", showNextGuest.bind(null, i+1), false);
});
This can be shortened to:
var links = document.querySelectorAll("fieldset a:first-of-type");
[].forEach.call(links, function(link, i){
link.addEventListener("click", showNextGuest.bind(null, i+1), false);
});
function nextGuest () {
for(var i = 0; i < 5; i++){
document.getElementsByTagName('fieldset')[i]
.getElementsByTagName('a')[0]
.addEventListener('click',function(){
showNextGuest(parseInt(i + 1));
}, false);
}
}
Benjamin's answer above is the best given, so I have accepted it.
Nevertheless, for the sake of completeness, I wanted to show the (simpler, if less elegant) solution I used in the end, so that future readers can compare and contrast between the code in the question and the code below:
<script>
var initiateShowNextGuest = [];
function showNextGuest(j) {
document.getElementsByTagName('fieldset')[j].style.display = 'block';
}
function initiateShowNextGuestFunction(i) {
return function() {
var j = i + 1;
document.getElementsByTagName('fieldset')[i].getElementsByTagName('a')[0].addEventListener('click',function(){showNextGuest(j);},false);
};
}
function initiateShowNextGuests() {
for (var i = 0; i < 5; i++) {
initiateShowNextGuest[i] = initiateShowNextGuestFunction(i);
initiateShowNextGuest[i]();
}
}
window.onload = initiateShowNextGuests();
</script>
In summary, the function initiateShowNextGuests() loops through (and then executes) initiateShowNextGuestFunction(i) 5 times, setting up the 5 anonymous functions which are manually written out in the code in the original question, while avoiding the closure-loop problem.

JavaScript converting an array to array of functions

Hello I'm working on a problem that requires me to change an set array of numbers into an array that returns the original numbers as a function. So we get a return of a2 instead of a[2].
I dont want the answer I just need a hint. I know i can loop through the array and use .pop() to get the last value of the array, but then I dont know how to convert it to a function from there. any hints?
var numToFun = [1, 2, 3];
var numToFunLength = numToFun.length;
for (var i = 0; i < numToFunLength; i++) {
(function(num){
numToFun.unshift(function() {
return num;
});
}(numToFun.pop()))
}
DEMO
basically it pops out a number from the last, builds a function with that number returned, and put back into the first of the array. after one full cycle, all of them are functions.
here's the catch: how this works, it's up to you to research
why the loop does not look like the straightforward pop-unshift:
for (var i = 0; i < numToFunLength; i++) {
numToFun.unshift(function() { //put into first a function
return numToFun.pop() //that returns a number
});
}
and why i did this: (HINT: performance)
var numToFunLength = numToFun.length;
There's three important steps here:
Extract the number value from the array. Within a loop with an iterator of i, it might look like this:
var num = numArray[i];
This is important, because i will not retain its value that it had when you created the new function - it'll end up with the last value it had, once the for loop is finished. The function itself might look like this:
function() { return num; }
There's no reference to i any more, which is important - to understand better, read about closures. The final step would be to add the new function to the array of functions that you want.
...and you're done!
EDIT: See other's answers for good explanations of how to do this right, I will fix mine also though
As others have pointed out, one of the tricky things in javascript that many struggle with (myself included, obviously) is that scoping variables in javascript is dissimilar to many other languages; scopes are almost purely defined by functions, not the {} blocks of, for example, a for loop, as java/C would be.
So, below you can see (and in other answers here) a scoping function can aid with such a problem.
var numArray = [12, 33, 55];
var funcArray = [];
var numArrLength = numArray.length; // Don't do this in for loop to avoid the check multiple times
for(var j=0; j < numArrLength; j++) {
var scopeMe = function() {
var numToReturn = numArray[j];
console.log('now loading... ' + numToReturn);
var newFunc = function() {
return numToReturn;
};
return newFunc;
}();
funcArray.push(scopeMe);
};
console.log('now me');
console.log(funcArray);
console.log(funcArray[0]());
console.log(funcArray[1]());
console.log(funcArray[2]());
console.log(funcArray[1]()); // To ensure it's repeatable
EDIT my old bad answer below
What you'll want to do is something like
var funcArray = [];
for(...) {
var newFunc = function() {
return numArray.pop();
}
funcArray.push(newFunc);
}
The key here is that functions in javascript can be named variables, and passed around as such :)

Trying to avoid eval getting array element from window object

I've got a function that wants to access a global variable, the name of which arrives as a string argument. This is how it looks now, using eval:
function echoVar(whichone){
document.write(eval(whichone));
}
I thought I'd just use the window[] syntax and have this:
function echoVar(whichone) {
document.write(window[whichone]);
}
If I create a var and call it like this, it doc writes ABC as expected:
var abc = "ABC";
echoVar("abc");
If the var I want to access is an array element though, it doesn't work:
var def = ["DEF"];
echoVar("def[0]"); //fails with undefined
Obviously that's actually executing window[def[0]] which rightly gives undefined (because there's no variable called DEF). What I actually want to happen is that it executes window["def"][0].
The only way I know to achieve this, is to do a split on the whichone parameter with "[" as the delimiter and then use the split [0] as the window index and a parseInt on split [1] to get the index, like this:
function echoVar(whichone){
if(whichone.indexOf("[")==-1){
document.write(window[whichone]);
}
else{
var s = whichone.split("[");
var nam = s[0];
var idx = parseInt(s[1]);
document.write( window[nam][idx] );
}
}
Am I overlooking something obvious? I'd rather keep the eval than have to do all that.
If you dislike using eval in your code, you can always do this:
function echoVar(whichone) {
document.write(Function("return " + whichone)());
}
Unless this is some sick experiment, you should never be writing Javascript code that looks like this. This is terrible; you need to re-think your design. I know this isn't what you're looking for, but it's the right answer.
The fact is you've got a piece of a javscript expression in a string so you either have to parse it yourself or use eval to parse it for you unless you change the way it's passed like this:
function echoVar(a,b) {
var x = window[a];
if (b) {
x = x[b];
}
document.write(x);
}
And, then you can pass it differently like this:
var def = ["DEF"];
echoVar("def", 0); // def[0]
You could even make this support multiple dimensions if you needed to.
function echoVar(a) {
var x = window[a];
for (var i = 1; i < arguments.length; i++) {
x = x[arguments[i]];
}
document.write(x);
}
var def = {myObject: {length: 3}}
echoVar("def", "myObject", "length"); // def["myObject"]["length"] or def.myObject.length
You can see it work here: http://jsfiddle.net/jfriend00/dANwq/
It would be simpler to lose the brackets and call the item with dot notation
function reval(s, O){
s= String(s);
O= O || window;
var N= s.split(".");
while(O && N.length) O= O[N.shift()];
return O || s;
}
window.def= ['definition'];
alert(reval('def.0'))
/* returned value: (String)
definition
*/

Categories

Resources