Procedurally Generated Variable Naming - javascript

So I am currently attempting to procedurally generate variable names based on some other things I want to do later in the function.
However when I attempt this as a trial function:
var gridCoord = [[1,2]];
var 'run' + gridCoord[0][0] + gridCoord[0][1] = function() {
console.log("Success!");
}
run12();
I am receiving syntax errors in the console.

You can't do it like that. Use dynamic naming of objects.
window['run'+gridCoord[0][0]+gridCoord[0][1]] = function() {
The window object is a global object; these functions can be called normally as any other global function can be called.

window['run'+gridCoord[0][0]+gridCoord[0][1] ]= function(){
console.log("Success!");
}
In the global scope, all variables are children of the window property

Related

call a js function based on the argument passed

I'm trying to call a js function within another one, but use the argument to specify the function. ie depending on the argument passed, it will call a different function
function toggle(n){
if (sessionStorage['toggle'+n]== 0){
check+n();
}
else
}
So, for example, if the argument 'Balloons' was passed as n, then it will call the function checkBalloons(). "check+n();" is not currently working here. Sorry for my lack of simple js syntax!
If the function is defined in the global scope (browser) you can do:
window["check"+n]();
or some tenants like Node.js you would access it from global object.
global["check"+n]();
if it is a part of some other object then you would do the same.
obj["check"+n]();
Functions and properties defined on an object can be accessed using [] convention as well. i.e obj["propFuncName"] will give you reference to it, so in case of methods you add () to invoke it.
If the function is global, you would do this:
window["check" + n]();
or, you could put your function in an object like so:
myNamespace = {};
myNamespace.checkSomething = function(){ /* ... */ }
// call it like this:
myNamespace["check" + n]();
The answers thus far are correct, but lack explanation.
In JavaScript, you cannot call a function by name when that name is a string. What you can do is retrieve a value from an object by name, and if that value happens to be a function, you can then call it. For example:
var myObject = {};
myObject.myFunction = function() { alert('test!'); };
// Get the property on `myObject` called `myFunction`
var theFunctionLookup = myObject['myFunction'];
// Since that property was a function, you can call it!
theFunctionLookup();
In the browser, functions that are defined in the global scope are attached to the window object. For example, this works:
function myFunction() { alert('test'); }
var theFunctionLookup = window['myFunction'];
theFunctionLookup();
You can shorten the last two lines into one:
function myFunction() { alert('test'); }
// Look up and call the function in one line.
window['myFunction']();
For the same reasons, you can use a dynamically-calculated string to look up functions.
function checkBalloon() {
alert('checking balloon');
}
function toggle(n){
if (sessionStorage['toggle'+n]== 0){
window['check' + n]();
check+n();
}
}
toggle('Balloon');
if you do this way:
if (sessionStorage['toggle'+n]== 0){
window["check" + n]();
}
will work

JS λ-functions & "upper context" variables

Say I have some context where variables are set and a λ-function is called which uses them directly:
function outerContext(){
...
var data = ...; // some data the script uses
...
someObject.method = function(){
data; // the variable is used here
};
...
}
I know that the dynamically created function has a snapshot of the context it was created in, so data variable is accessible there.
What are the dangers I may face with such an approach when I use this dynamically created method? Should I always give this data as an argument or is it ok?
The inner function does not have access to a "snapshot", it has full access to the data variable.
function outer() {
var data = 1;
...
someObject.method = function () {
data = 42;
};
someObject.method();
// data == 42
}
(The real explanation being that when using data in the inner function, Javascript will try to figure out which scope data is in. It will traverse up the scope chain to find the place where the variable was created, and that's the variable that will be used.)
There's no "danger", this is one of the core competencies of Javascript. It's like an object method modifying an object's properties. Of course you need to take care what you want to do, do you really want to modify the variable or do you just want to use it locally?
For the "snapshot", you need to use a closure:
function outer() {
var data = 1;
...
someObject.method = (function (data) {
return function () {
data = 42;
}
})(data);
someObject.method();
// data == 1
}
I can't really think of any "dangers" besides the possibility of causing a circular reference and thus a memory leak in case of DOM objects or such.
It works much like a private variable in a class.

How do you reference a custom object outside of the function it was created in with JavaScript?

I'm currently using JavaScript and jQuery.
I have an function which executes once the document is ready, and inside that I am creating objects which contain various attributes.
Within the same function, I can access these new object's attributes no problem, however once I'm inside a different function I can't seem to reference them properly and therefore cannot access the objects or the information inside them.
What's the correct way to reference the attributes of an object which was created in a different function to the one looking for the information?
In general you can't reference an object that was created in a different function. The scoping rules do not allow that.
However, if you create your sub functions inside of the main JQuery ready function, you can create your objects as local variables to the ready function and use them in your other functions.
This would create a closure allowing the variables to still exist yet not be in the global scope.
Something like this:
$(function () {
var MyObj = {"CT":0};
function Inc(){
MyObj.Ct++;
}
$("INPUT[type=button]").click(Inc);
})
Create the a global refernence to the object outside of the function, e.g.:
var obj;
function func1()
{
obj = 1;
}
function func2()
{
alert(obj);
}
The best way would be to create a global object which holds all that data.
var myGlobalData = function(){
// private data
var some = 'data',
foo = 'bar';
// public
return {
publicfunction: function(){
alert(foo);
return(some);
}
}
};
within your ready code you can create an instance of that
$(document).ready(function(){
var myData = new myGlobalData();
myData.publicfunction();
});
Note that in this example, you can't access 'some' and 'foo' with
myData.foo = 'bar'; // not possible
because those are 'private' to the object. If you write an object in that manner, you
can simulate a more OOP style.
I have an function which executes once
the document is ready, and inside that
I am creating objects which contain
various attributes.
Define these objects as properties of the global object (window) and you'll be fine.
function onready() {
window.myObject = {};
}
function otherFunction() {
window.myObject.fu = "bar";
}

How do I create a random method name

I plan on using JSONP to call an external web service to get around the fact that I don't want to create a global function that could potentially conflict with the calling page. I thought that creating a random function name and passing it up would work. Something like this:
<script src="www.foo.com/b?cb=d357534">
where cb is the callback function name, the server would return
d357534({my json data});
What I want to know is how to create the random function name, I'm sure I could use eval but is this the best way to go about it?
Essentially, what I am trying to do is this:
var d + Math.floor(Math.random()*1000001) = function(){...
This should do what you want. You need to save the function name somewhere so that you can pass it to the server, but you can do that inside of a local scope to avoid polluting your global namespace.
var functionName = 'd' + Math.floor(Math.random()*1000001);
window[functionName] = function() { ... }
To make a randomly-named global variable you could do this:
window['randomvar' + Math.floor(Math.random()*1000001)] = function() { ... };
now of course you've got the problem of remembering the random name somewhere. You could make up a random name for that variable too. Then you'd have to remember the name of that variable, so that you could look at its value and then know how to find your function. After a while, things are going to start getting weird.
Why don't just use a counter and increment it each time you need a new function:
var name = "callback" + window.COUNTER++;
window[name] = function() { ... };
If you want to avoid littering the global namespace with too many references you could (and should) attach the counter and callbacks to a single global object:
var JSONP = window.JSONP;
var name = "callback" + JSONP.COUNTER++;
JSONP[name] = function() { ... };
In this case you could call the method like this:
JSONP.callback_12(json);
Of coarse you have to initialize the JSONPobject and the COUNTER variable first.

Referencing an object to be augmented in javascript

I am trying to localize everything to a namespace in javascript. So I have objects that follow a naming convention like:
myapp.utilities.file.spinner
etc...
My question is, is there a way to avoid repeating that big string everytime I want to augment the object with a property or a method. Currently my code looks like this...
myapp.utilities.file.spinner.method1 = function() { };
myapp.utilities.file.spinner.method2 = function() { };
etc.
Something like this...
spinnerPath.method1 = function()
...where spinnerPath stands for myapp.utilities.file.spinner, would be nicer. But from my understanding I cannot just say
spinnerPath = myapp.utilities.file.spinner
as that will create another object in the global space.
Thanks
The code you're using won't actually create a new object, merely a new global variable referring to the existing object. It will pollute the global namespace however, so if you're looking to avoid that, you have several options:
You can use with, but don't because it will probably cause you more heartache than it's worth.
You can make a shorthand pointer variable inside each function outside of the global namespace: var s = myapp.utilities.file.spinner;, but this is annoying.
(Probably the best option) create a "private namespace" using an immediate-call function:
(function (S)
{
S.method1 = function(){/*whatever*/};
S.method2 = function(){/*whatever*/};
})(myapp.utilities.file.spinner)
Try this:
(function(){
var spinner = myapp.utilities.file.spinner;
spinner.method1 = function(){};
})();
myapp.utilities.file.spinner.method1 = function() { };
myapp.utilities.file.spinner.method2 = function() { };
...
// Somewhere else in your code, create a temp local called "spinner"
// that references your longer path object.
var spinner = myapp.utilities.file.spinner;
spinner.method1();
You can just make a temporary local variable wrapped in an anonymous function:
(function(){
var spinnerPath = myapp.utilities.file.spinner;
spinnerPath.method1 = function() { };
spinnerPath.method2 = function() { };
spinnerPath.method1();
})();
Here, spinnerPath is in fact a local reference to the global myapp.utilities.file.spinner object, not a copy. Objects in JavaScript are references, so if you create a local variable that points to it, you will not create a copy or pollute the global namespace.

Categories

Resources