0

I have a global variable:

var chart;

A function which creates the chart:

function setChart(variableName, chartContainer){

variableName = new CanvasJS.Chart(chartContainer, {**params**});

 variableName.render();

};

I call setChart

setChart(chart, "chartContainDiv");

If I call chart.render(); later, it doesn't work.

How can I achieve this? / What am I misunderstanding?

OliverJ90
  • 1,291
  • 2
  • 21
  • 42
  • You're misunderstanding how JavaScript works; you can't do it like that. If you want to refer to a variable by name the closest equivalent would be to create an object and refer to its properties by name. – Dave Newton Sep 09 '14 at 13:38
  • 2
    That's quite an edit. In any case, the issue is the same--you're setting a variable that's local to the function. If you need more than one instance, use an object, like I already said. If you need a single instance, then just use the global. – Dave Newton Sep 09 '14 at 13:48
  • You are confusing passing [by value and passing by reference](http://snook.ca/archives/javascript/javascript_pass). When you pass `chart` to `setChart` you can't assign it a value because you did not pass its reference you passed its value (which is `undefined` in your example). – Alex W Sep 09 '14 at 13:48
  • @DaveNewton I know, sorry, I'm having one of those days. – OliverJ90 Sep 09 '14 at 13:50
  • @AlexW ok, so if I want to do the above, so that I can create a few different charts using the setChart function how would I do it? – OliverJ90 Sep 09 '14 at 13:57
  • @OliverJ90 I posted an answer below – Alex W Sep 09 '14 at 14:15

3 Answers3

3

Since you're passing a string into the function, you end up trying to assign this:

setVar("globalVar");
// In setVar...
"globalVar" = 5

which obviously doesn't work. Passing in just the variable name itself will almost work as expected:

setVar(globalVar);
// In setVar...
globalVar = 5

HOWEVER

Because of variable scope, inside the setVar function you have a local variable with the same name as the global one. Doing any assignation here will just set the local variable to 5, where the global variable will remain at whatever value it used to be.

var myVar = 1;
function setVar(globalVar) { globalVar = 5; alert(globalVar); }
setVar(myVar); // alerts 5
alert(myVar); // alerts 1

Interestingly, if you pass the string in then you're able to set it via array-access on the window object:

setVar("globalVar");
// In setVar...
window[variableName] = 5; // window["globalVar"] = 5;

but trying to do that by passing the variable itself in doesn't work...

setVar(globalVar);
// In setVar...
window[globalVar] = 5; // window["5"] = 5 // or whatever globalVar contains

The TLDR version of this is that this is the only way to do this exactly as you're trying to do in the OP (although there are other ways such as Ahmad's answer, where you set a specific variable without passing it):

var myVar = 1;
function setVar(varName) { window[varName] = 5; }
setVar('myVar');
Joe
  • 15,669
  • 4
  • 48
  • 83
  • Passing in the variable name won't work as expected, unless you don't expect globalVar to be set to 5 outside of the function. – Dave Newton Sep 09 '14 at 13:42
  • @DaveNewton I was halfway through typing as you were discussing :P I've updated it to mention the scoping, as the window[string-var-name] still works. – Joe Sep 09 '14 at 13:44
  • Removed my original comment, as it is no longer true! :) – UweB Sep 09 '14 at 13:45
0

first you have to be clear on the scopes of variables and global variables. In you example, there is no line where you set globalVar to 5. You only set a local variable for the function setVar called variableName to 5.

what you should do is:

var globalVar;

function setVar(){
  globalVar = 5;
};

now if you want to have a global variable or a set of global variables then you should have them in an object and then have a function that take that variable name and an optional value that you to assign.

    var globalVariables = {"globalvar1" : "", "globalvar2" : "", .... };
    function setGlobalVar(variableName, Value) {
       globalVariables[variableName] = value;
    }

setGlobalVar ('globalvar1', 5); // this would do it
AhmadAssaf
  • 3,556
  • 5
  • 31
  • 42
  • `window` is an object and the variable is in the global scope, so you can reference them by array notation via `window[variableName]` rather than having to put them inside another container object – Joe Sep 09 '14 at 13:47
  • its always good practice to minimize adding to `window` to keep global namespace clean (http://stackoverflow.com/questions/3679634/is-setting-properties-on-the-window-object-considered-bad-practice) – AhmadAssaf Sep 09 '14 at 13:49
  • Definitely, but he's already told us that it's a global variable (line 1 of the OP) and unless you're scoping this inside something else which you haven't shown in your answer, you're just creating a global object yourself, called `window.globalVariables` :-) – Joe Sep 09 '14 at 13:50
  • i was not clear on the global variable if its on the window or on a function scope :) apparently he edited the question now – AhmadAssaf Sep 09 '14 at 13:52
0

Use the function as a factory that returns a chart object, instead of passing it an empty variable. This uses the exact same concept, by creating an object and then returning that object, but it doesn't use a CanvasJS object for simplicity purposes:

function setChart(chartContainer) {
    var variableName = new String(chartContainer);
    return variableName.toUpperCase();
};

var chart = setChart("chartContainDiv");
var chart2 = setChart("blahBlah");
console.log(chart.toString());    // "CHARTCONTAINDIV"
console.log(chart2.toString());   // "BLAHBLAH"

http://jsfiddle.net/n8Lg4wqy/3/

Alex W
  • 37,233
  • 13
  • 109
  • 109