Running functions using string name from array [duplicate] - javascript

This question already has answers here:
How to execute a JavaScript function when I have its name as a string
(36 answers)
Closed 5 years ago.
I have an array that has a bunch of function names. I am not storing the function in an object.
for (i = 0; i < view_functions.length; i++) {
view_functions[i]();
}
This doesn't work, any ideas?
Thanks.

The code you posted works, so perhaps the code that defines the functions isn't quite right. Here is a fully working example.
function yep() {
alert('Yep');
}
function again() {
alert('Again');
}
var view_functions = [
yep,
again
];
for (var i = 0; i < view_functions.length; i++) {
view_functions[i]();
}
If you wanted to get a bit of design help in your code, you could introduce a factory. This has the added benefit of making unknown function names explicit.
function yep() {
alert('Yep');
}
function again() {
alert('Again');
}
function functionFactory(name) {
switch (name) {
case 'yep':
return yep;
case 'again':
return again;
default:
throw `${name} not a known function in functionFactory`;
}
}
var view_functions = [
'yep',
'again'
];
for (var i = 0; i < view_functions.length; i++) {
var func = functionFactory(view_functions[i]);
func();
}
If you only have string names, I recommend not using string names... but you could go full-evil and use eval...
function yep() {
alert('Yep');
}
function again() {
alert('Again');
}
var view_functions = [
'yep',
'again'
];
for (var i = 0; i < view_functions.length; i++) {
var n = view_functions[i] + '()';
eval(n);
}
But why not store the actual functions in the array instead...

Related

How to get length of array inside of objects in javascript? [duplicate]

This question already has answers here:
Accessing an object property with a dynamically-computed name
(19 answers)
Closed 11 months ago.
Try to get length of array inside an object
image above is return of Res
I want to check if every tenor length is equal or more than zero.
But, I stuck in how to call itemCounter"i" when loop it
var tenorCount = Object.keys(res).length;
var flagTenor = false;
try{
for(var i=1;i<tenorCount;i++){
if (res.itemCounter_+i.tenor.length < 1){ //Stuck in here
flagTenor = true;
}
}
}catch(e){
console.log(e);
}
How to call itemCounter"i" correctly?
Try like this using template literals and computed property names
if (res[`itemCounter_${i+1}`].tenor.length < 1)
Example
const res = {
itemCounter_1: {
tenor: ["one"]
},
itemCounter_2: {
tenor: []
},
}
var tenorCount = Object.keys(res).length;
var flagTenor = false;
try {
for (var i = 0; i < tenorCount; i++) {
if (res[`itemCounter_${i+1}`].tenor.length < 1) {
flagTenor = true;
}
}
} catch (e) {
console.log(e);
}
console.log(flagTenor);

JSHint warning "Function declared within loop referencing an outer scope variable may lead to confusing semantics" . How can I improve the code?

JSHint shows the error:
"Function declared within loop referencing an outer scope variable may lead to confusing semantics".
How can I improve the following code to get rid of the warning?
var getPrecedence = function getPrecedence(operator, operators) {
var keys = Object.keys(Object(operators));
for (var i = 0, len = keys.length; i < len; i++) {
var check = Object.keys(operators[keys[i]]).some(function (item) {
return item === operator;
});
if (check) return operators[keys[i]][operator];
}
};
You are supposed not to use the function expression inside the loop body, but instead declare it outside:
function getPrecedence(operator, operators) {
function isOperator(item) {
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^
return item === operator;
}
var keys = Object.keys(Object(operators));
for (var i = 0, len = keys.length; i < len; i++) {
var check = Object.keys(operators[keys[i]]).some(isOperator);
// ^^^^^^^^^^
if (check) return operators[keys[i]][operator];
}
}
Of course the whole thing could be simplified by just using includes instead of some, and find instead of the loop:
function getPrecedence(operator, operators) {
var keys = Object.keys(Object(operators));
var opkey = keys.find(key =>
Object.keys(operators[key]).includes(operator)
);
if (opkey) return operators[opkey][operator];
}
And finally, Object.keys(…).includes(…) can be simplified to operator in operators[key].
Add it before calling the function, this one will bypass that check
/* jshint -W083 */

How to push a declared function into an array and later invoke it [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 5 years ago.
The following code works great. It pushes 10 unnamed functions into an array and then successfully executes the 7th item in the array.
var storeStuff = [];
for (let i = 0; i < 10; i++) {
storeStuff.push(function() {
console.log(i * i);
});
}
storeStuff[6]();
However the test function above is tiny. If I had a large function with many lines of code I'd likely want to declare it outside of the push.
For example what if I wanted to push a previously defined function and later invoke it like the example below?
var storeStuff = [];
function externalFunction(temp) {
console.log(temp * temp)
}
for (let i = 0; i < 10; i++) {
storeStuff.push(externalFunction(i));
}
storeStuff[6]();
Unfortunately this doesn't work as written and everything I've tried crashed and burned. What am I getting wrong?
Use function declaration as below
var storeStuff = [];
externalFunction = function(temp) {
console.log(temp * temp)
}
for (let i = 0; i < 10; i++) {
storeStuff.push(externalFunction);
}
storeStuff[6](6);

Having trouble detecting undefined objects in an array

Quick bit about my background:
-been learning for about 3 months;
-work in tech support for a small software company. 2 years exp.
-a lot of knowledge is secondhand and I am still learning the basics
I am trying to create an object every second. The object is created directly to the last position of an array that remembers a set quantity of objects created before the most recent one
function Fruit(name, position) {
this.name = name;
this.position = position;
}
var showXMostRecentFruits = 20;
var fruitCounter = 0;
function generateName() {
var name = 'Experimental Fruit' + fruitCounter;
return name;
}
var fruitsArray = [];
function shiftFruits() {
for (i = 0; i < showXMostRecentFruits; i++) {
fruitsArray[i] = fruitsArray[i + 1];
}
function updateFruitPositions() {
for (i = 0; i < showXMostRecentFruits; i++) {
fruitsArray[i].position = i;
}
}
var fruitTimer; //used for setting and clearing setTimeout
function createNewFruit() {
shiftFruits();
fruitsArray[showXMostRecentFruits - 1] = new Fruit(generateName());
updateFruitPositions();
fruitCounter += 1;
fruitTimer = setTimeout(function() {
createNewFruit();
}, 1000);
}
Say the function createNewFruit() is run once
createNewFruit();
Then I try to pull some meaning from the array
console.log(fruitsArray[19];
All I get is:
Fruit {}
undefined
This issue is when I want to run a loop (see updateFruitPositions()) that updates a propery of each object in the array, an error is returned that the objects are undefined. I get that they are undefined because they are not assigned to unique variables (at least not that I'm aware of). How can I identify the objects or how can I create unique containers for them so I access them in the array?
You need to test whether a given element is set to something before attempting to write to one of its properties.
Instead of this...
for (i = 0; i < showXMostRecentFruits; i++) {
fruitsArray[i].position = i;
}
Use this:
for (i = 0; i < showXMostRecentFruits; i++) {
if (fruitsArray[i])
fruitsArray[i].position = i;
}
You fill the array from the end, staring with element 20. Without the if (fruitsArray[i]), you're attempting to set undefined.position = i for the first 19 elements.
You could replace the showFruits function with something much more efficient:
function shiftFruits() {
if (fruitsArray.length > showXMostRecentFruits) {
fruitsArray.shift();
}
}
and updateFruitPositions only needs to update members that exist, the length is controlled by shiftFruits:
function updateFruitPositions() {
for (i = 0; i < fruitsArray.length; i++) {
fruitsArray[i].position = i;
}
}
or where forEach is supported:
function updateFruitPositions() {
fruitsArray.forEach(function(fruit, i){fruit.position = i});
}
so it only visits members that exist. And the createNewFruit has:
fruitsArray.push(new Fruit(generateName());

function return the same value

N_ALPHA = 6;
N_CHOICES = 4;
ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var alphabet = ALPHABET.substring(0, N_ALPHA);
var indexForm=new Array();
function guessStrToArr(inStr)
{
{
for (i=0;i<N_CHOICES;i++)
{
indexForm[i]=alphabet.indexOf(inStr.charAt(i).toUpperCase());
}
}
return indexForm;
}
function numBulls(guess, goal)
{
guess=new Array (guessStrToArr(prompt('enter your guess1')));
alert(guess);
goal=new Array(guessStrToArr(prompt('enter your guess2')));
var checkArray = new Array (guess.concat(goal);
alert(checkArray);
var count=0;
for (i=0;i<N_CHOICES;i++)
{
if (guess[i]===goal[i])
{
count++
}
}
return count;
}
numBulls();
when I run the above code, it returnt the same array, evern I type different code into prompt alet box. I don't know why, can you please help me?
Thank you very much.
indexForm is a global variable. When you call the guessStrToArr function for the first time array gets populated. The second time it gets repopulated. When you're doing the comparison, your comparing the array against itself. Try this:
function guessStrToArr(inStr) {
var indexForm = new Array();
for (i = 0; i < N_CHOICES; i++) {
indexForm[i] = alphabet.indexOf(inStr.charAt(i).toUpperCase());
}
return indexForm;
}
Also note that you are making no attempt to ensure that inStr.length is the same as N_CHOICES.

Categories