For instance, we have a variable and a function named foo and plus:
var foo = 2;
var plus = function(a,b){return a+b;}
and we have a string:
var s = '1 plus foo';
and now I want this string s convert to an array:
var array = [1, plus, foo]);
Please note this is not [1, 'plus', 'foo'] which conversion is rather easy and I know the way.
So, consequently, my Question would be
how to obtain a value(function) itself from strings?
and also please note that using eval to solve this issue is invalid since the purpose is not to evaluate but to construct an array from the string.
Thanks.
EDIT:
Since I use node.js
The global object is global
and
it seems
global.foo and var foo is different.
I felt that before this Question and that is why I asked here.
[1, global['plus'], global['foo']] should be invalid answer.
if you do s.split(' ');, you can use the strings in the array to call the requested functions:
window['plus']() // Call your functions like this.
Or to set them in an array:
var array = [1, window['plus'], window['foo']];
Then you'll have the function references stored in array.
My self answer:
var G = {};
var foo = G.foo = 2;
var plus = G.plus = function(a,b){return a+b;}
and we have a string:
var s = '1 plus foo';
and now I want this string s convert to an array:
var array = [1, G['plus'], G['foo']];
In this way, we can avoid Global Variables and keep var foo format, and at the same time, allow the value accessible with G object + ['string'].
Related
Say I have two arrays and an integer.
var int = 1; //or 0 depending on other circumstances
var ar0 = [0]
var ar1= [1]
Is there a way to use the integer to determine which array to write to? Like if int = 1 then I could have something along the lines of
'ar'+ int
that would choose the correct array? Or do I need a bunch of if-statements?
I'd like to be able to identify and edit the array that I need to edit by a number that was given to me.
What you are trying to do is to set up an environment. However, you cannot access variables in what is called the Variable Environment in JavaScript by name such as with 'ar' + int. If it is in the global scope that is kind of possible by using window['ar'+int] but this is bad practice and also assumes that the variable is global.
What you should do is wrap those in an object and then use the reference in the object to locate the array.
var int = 1;
var environmentObject = {};
environmentObject['ar0'] = [0];//string notation assignment example
environmentObject.ar1 = [1];//dot notation assignment example
and now you can easily access your array by name
var myarr = environmentObject[`ar`+int];
You could use an eval
var int = 1;
var ar0 = [0];
var ar1 = [1];
eval('ar' + int).push(2);
console.log(ar1); // 1, 2
But it is a bad practice. For your case, if you have only two integers(0, 1) better to use if statement:
if(int) { // 0 is falsy, 1 is truth
ar1.push(...);
} else {
ar0.push(...);
}
Or as Oriol mentioned, using ternary operator:
(int ? ar1 : ar0).push(...);
this works:
var f = function(a){
a.push(1);
};
var a = [];
f(a);
console.log(a);//[1];
But this:
var f = function(a){
a = a.concat([1]);
};
var a = [];
f(a);
console.log(a);//[];
Does not work. With work I mean that the changes made persist after the function call.
Now I realise that this most likely has something to do with the arguments being passed 'as reference by value', meaning that a change in reference (ie assigning a new object) does not persist after the function call.
So I wonder, is there a persistent version of concat? Or do I manualy have to push all elements from one array into the other?
Edit: All of you suggesting to return the newly created array: that's pretty much exactly what I don't want. If I wanted to do that I wouldn't have created this question. And I certainly would not have ended it specifically asking for a persistent version of concat.
concat returns a new array, it doesn't mutate the source array.
var f = function(a){
return a.concat([1]);
};
var a = f([]);
console.log(a);//[1];
If you do want to mutate the array, just use push.apply to pass array elements as individual arguments to the push function.
var f = function(a) {
a.push.apply(a, [1]);
};
var a = [];
f(a);
console.log(a); //1
That's because the function parameter, a, is not the same as the variable a declared in the outer scope. When you assign a new value to the parameter a, it has no effect on the outer variable.
a = a.concat([1]);
Instead, simply return the new array, and use the return value in the outer scope, like this:
var f = function(a){
return a.concat([1]);
};
var a = [];
a = f(a);
Or perhaps consider using push like this:
var f = function(a){
Array.prototype.push.apply(a, [1, 2, 3]);
};
This will push multiple values onto the source array, so it's pretty much equivalent to concat except that it modifies the original array.
How would I create dynamic variable names in NodeJS? Some examples say to store in the window variable, but I was assuming that is client-side Javascript. Correct me if I'm wrong.
Generally you would do something like:
var myVariables = {};
var variableName = 'foo';
myVariables[variableName] = 42;
myVariables.foo // = 42
In node.js there is the global context, which is the equivalent of the window context in client-side js. Declaring a variable outside of any closure/function/module as you would in plain Javascript will make it reside in the global context, that is, as a property of global.
I understand from your question that you want something akin to the following:
var something = 42;
var varname = "something";
console.log(window[varname]);
This in node.js would become:
var something = 42;
var varname = "something";
console.log(global[varname]);
Just don't know what a bad answer gets so many votes. It's quite easy answer but you make it complex.
var type = 'article';
this[type+'_count'] = 1000; // in a function we use "this";
alert(article_count);
One possible solution may be:
Using REST parameter, one can create an array and add each dynamic variable (REST parameter item) as an object to that array.
// function for handling a dynamic list of variables using REST parameters
const dynamicVars = (...theArgs) => {
let tempDynamicVars = [];
// as long as there are arguments, a new object is added to the array dynamicVars, creating a dynamic object list of variables
for (let args = 0; args < theArgs.length; args++){
const vName = `v${args}`;
tempDynamicVars = [...tempDynamicVars, {[vName]: theArgs[args]}]; //using spread operator
// dynamicVars.push({[vName]: theArgs[args]}); // or using push - same output
}
return tempDynamicVars;
}
// short version from above
// const dynamicVars = (...theArgs) => theArgs.map((e, i) => ({[`v${i}`]: e}));
// checking
const first = dynamicVars("F", 321);
console.log("Dynamic variable array:", first);
console.log(` - ${first.length} dynamic variables`);
console.log(" - second variable in the list is:", first[1], "\n");
console.log(dynamicVars("x, y, z"));
console.log(dynamicVars(1, 2, 3));
console.log(dynamicVars("a", "b", "c", "d"));
I've found this topic which I've implemented (see accepted answer):
javascript equivalent of PHP's call_user_func()
However, I am having a problem with multiple parameters. I realize what I was doing was turning my parameters into strings and treating it like 1 parameter, but I don't know how to fix this because I am dynamically creating the parameters.
Meaning, I have defined in my code the following:
var a = new Array();
a[0] = new Array();
a[0][0] = 'alert';
a[0][1] = '\'Hello World\'';
a[1] = new Array();
a[1][0] = 'setTimeout';
a[1][1] = 'alert("goodbye world")';
a[1][2] = '20';
Later, I was calling them like this:
var j = 0;
var len = 0;
var fx = '';
var params = '';
for( i in a ){
params = '';
len = a[i].length;
fx = a[i][0]; // getting the function name
a[i].splice( 0, 1 ); // removing it from array
if( len > 1 ){
params = a[i].join(", "); // trying to turn the parameters into the right format, but this is turning it into strings I think
params = params.replace(/\\'/g,'\''); // bc i was adding slashes with PHP
}
window[fx](params);
}
I don't have to use arrays to do this. I don't understand JS OOP (haven't tried yet), though I am comfortable with PHP OOP, so I don't know if there is a way to do this there.
Any help on passing multiple parameters would be appreciated.
Thanks.
First thing to do: Scrap your entire code, start over. Your approach will not get you anywhere where you'd want to be. (Unfortunately I can't tell you where you'd want to be because I cannot make sense of your example.)
There are three ways to call a function in JavaScript.
function foo() { console.log(arguments); }
// 1. directly
foo(1, 2, 3);
// 2. trough Function.call()
foo.call(this, 1, 2, 3);
// 3. trough Function.apply()
var args = [1, 2, 3];
foo.apply(this, args);
call and apply are similar. They let you decide which object the this keyword will point to inside the function (that's the important bit!).
apply accepts an array of arguments, call accepts individual arguments.
The closest thing to call() is PHP's call_user_func(). The closest thing to apply() is PHP's call_user_func_array().
JavaScript objects share something with PHP arrays: They are key/value pairs.
// an anonymous function assigned to the key "foo"
var obj = {
foo: function () { console.log(arguments); }
};
This means you can access object properties either with the dot notation:
// direct function call
obj.foo(1, 2, 3);
Or through square bracket notation (note that object keys are strings):
var funcName = "foo";
obj[funcName](1, 2, 3);
obj[funcName].call(obj, 1, 2, 3);
obj[funcName].apply(obj, [1, 2, 3]);
Square bracket notation gives you the freedom to choose an object property dynamically. If this property happens to be a function, apply() gives you the freedom to choose function arguments dynamically.
Every top-level function that has not been declared as the property of some object will become the property of the global object. In browsers the global object is window. (So the function foo() in my first code block above really is window.foo.)
Note that this does not work like in PHP. It will point to the object the function has been called on, not the object the function "belongs to". (The concept "belongs to" does not really exist in JavaScript. Things can be modeled that way, but it's only a convention.)
With direct calling (obj.foo(1, 2, 3)), this will point to obj. With call and apply, this will point to whatever object you want to. This is a lot more useful than it sounds at first. Most of the time when you want to call functions dynamically, you will end up using apply.
Check out Function.apply:
function test(a, b) { console.log([a, b]) }
test.apply(null, [1, 2]); // => [ 1, 2 ]
Late to the party, but now with ES6 you can simply do
function FunctionX(a,b,c,d){
return a + b + c + d;
}
let fx = "FunctionX";
let params = [ 1, 10, 100, 200 ];
let answer = window[fx]( ... params);
let answer2 = globalThis[fx]( ... params ); // this is more cross-platform
to unpack your argument array
I'm trying to create an associative array, create an empty array, and then add a (indexName -> value) pair:
var arrayName = new Array;
arrayName["indexName"] = value;
// i know i can also do the last line like this:
arrayName.indexName = value;
When I assign the value to the indexName I want indexName to be dynamic and the value of a variable. So I tried this:
arrayName[eval("nume")] = value;
Where:
var var1 = "index";
var var2 = "Name";
var nume = '"' + var1 + var2 + '"';
but: alert(arrayName["indexName"]); doesn't return "value"... it says "undefined"
Is there something I’m missing? (I’m not familiar with eval() ); if the way I’m trying is a dead end, is there another way to make the index name of the associative array value dynamic?
At first I don't think you need a real array object to do what you need, you can use a plain object.
You can simply use the bracket notation to access a property, using the value of a variable:
var obj = {};
var nume = var1 + var2;
obj[nume] = value;
Array's are simply objects, the concept of an "associative array" can be achieved by using a simple object, objects are collections of properties that contain values.
True arrays are useful when you need to store numeric indexes, they automatically update their length property when you assign an index or you push a value to it.
You would use objects to do that:
var hash = {}
hash["foo"] = "foo";
hash.bar = "bar";
// This is the dynamic approach: Your key is a string:
baz = "baz"
hash[baz] = "hello";
To iterate, just use a for loop or $.each() in jQuery.
use arrayName[var1+var2]
Note that arrayName.var is the same as arrayName["var"] -- it's just syntactic sugar. The second form is mostly used when dealing with the kind of problems that you are facing - dynamic object keys, and keys that are not alphanumeric (think of arrayName[".eval()"]; this is a perfectly legal object key that has nothing to do with the javascript eval() function)
Are you looking for variableName = 'bla'+'foo'; arrayRef[variableName] = 'something'; ?
And even so, you should use an object literal instead. x = {}; x[variablename] = 'blah';
You want a plain object with the same bracket notaiton here, like this:
var arrayName = {};
arrayName["indexName"] = value;
Indeed, there was no need for an array object, a simple object did the job; further more an array introduced the need to use quotes inside the square brackets obj["var1 + var2"] to access the object property's value and not the value associated with an index (i think); the quotes transformed "var1 + var2" into a string. Using a simple object eliminated the need for quotes, so I can use obj[var1 + var2], wich worked :)
Thanks everyone !
I did something like like following;
let parentArray = [];
let childArray = [1, 2, 3];
childArray.name = 'my-array-1';
parentArray.push(childArray);
To access that by name in ES6;
parentArray.filter(x => x.name == 'my-array-1');