-3

How can I access variable C?

test = function(){
    a = 1;
    b = 2;
    c = a+b;
    return c
}
console.log(c)

Returns:

Uncaught ReferenceError: c is not defined

EDIT: Please disregard above question

To elaborate more on this. I am new to JavaScript and am stuck on a block of code that I can't get to work. I tried to simplify the problem I was having but I think that may have backfired...

Here is the full code that I am having trouble with. I need to access the variables inside of getAPIData.onload, But am getting "undefined" What is the best way to access these values?

getData();

function getData(){
  var activeMachines = [41, 44, 45]
  var dict = {};
  let data = activeMachines.reduce((obj, machineID) => {
    var getAPIData = new XMLHttpRequest();
    var url = 'http://127.0.0.1:8000/processes/apidata/' + machineID + '/';
    getAPIData.open('GET', url);
    getAPIData.send();
    getAPIData.onload = function(){
      var APIData = JSON.parse(getAPIData.responseText);
      dict['temp' + machineID] = APIData[0].tempData;
      dict['humid' + machineID] = APIData[0].humidData;
      timeValue = String((APIData[0].dateTime));
      dict['time' + machineID] = new Date(timeValue);
    }
    temp = dict['temp'+ machineID];
    humidity = dict['humid'+ machineID];
    time = dict['time'+ machineID];
    obj['machine_'+ machineID] = {temp, humidity, time}
    return obj
  }, {})
  console.log(data);
}

This returns the data dictionary, but all of the values are undefined. Any help is appreciated. I will read more into JavaScript scope as others have suggested.

MattG
  • 1,682
  • 5
  • 25
  • 45
  • 2
    Try `console.log(test())`. Also read up on how variable scope in javascript works – charlietfl Oct 28 '18 at 19:07
  • 1
    It has to do with scopes. `c` isn't available outside your function. Read some about this at https://www.w3schools.com/js/js_scope.asp Also, `test` is never called, so `c` is never set (altough it would only be avalable inside the function itself) – Philip Oct 28 '18 at 19:08
  • You need to learn about scopes. Here is a good article https://codeburst.io/javascript-a-basic-guide-to-scope-9682d57be6fc – tgo Oct 28 '18 at 19:09
  • 1
    There is no variable `c` since you were never calling the `test()` function! Also make sure to [declare your variables](http://blog.niftysnippets.org/2008/03/horror-of-implicit-globals.html) – Bergi Oct 28 '18 at 19:09
  • Oh, your edit makes this into a completely different question. See https://stackoverflow.com/q/23667086/1048572 for why it doesn't work. I'm wary to close as a duplicate, because you also have the problem of doing this asynchronous stuff in a loop. Try to get familiar with promises, then chain the promises for the XHRs in that `reduce`. – Bergi Oct 28 '18 at 19:54
  • Yeah I now realize that... Wasn't sure if I should delete it and repost a new question. Let me know if you think I should. Either way. I have been banging my head against the wall trying to get this to work, I feel like I'm close, but maybe not! – MattG Oct 28 '18 at 20:02

2 Answers2

1

c is a global variable that is created by calling the anonymous function assigned to the global variable test. However, you never call the anonymous function assigned to test, therefore the variable never gets created.

So, the obvious solution is to just call the anonymous function assigned to test:

test();

console.log(c);
// 3

However, this is a really bad idea. Global variables are evil, evil, evil. They tie together disparate parts of your program into a giant tangled mess: since they are accessible from everywhere, you have to assume that they may be accessed from everywhere. And changing them in one place may change the behavior of some completely unrelated code in a completely different part of your code.

Actually, it is even worse: since they are global, changing them in one place may not only change the behavior of some completely unrelated code in a completely different part of your code, it may even change the behavior of some completely unrelated code in a completely separate part of someone else's code!

The only way to avoid this, would be to invent unique names for every global variable, otherwise they are going to clash. In fact, you would need to invent a unique name for every global variable that was ever written, is written, and will be written by every programmer in the universe for all eternity!

But actually, there is no need for global variables here at all, since you actually return the value of c in your anonymous function. You can make those variables local to your function and simply use the return value. In fact, you don't even need variables at all, since you never "vary" them, you can make them constants instead.

Note: in modern ECMAScript, you should always prefer consts (unless you have a very good reason to use a let) and never use var or even worse (like you are doing here) implicit global variable definition. So, your code, in modern ECMAScript, should look like this:

const test = function () {
    const a = 1, 
        b = 2, 
        c = a + b;
    return c;
}

console.log(test());

Also, since you don't give your function a name and don't rely on dynamic scoping of this, you can use arrow function literal syntax:

const test = () => {
    const a = 1, 
        b = 2, 
        c = a + b;
    return c;
}

console.log(test());

or just give your function a name:

function test() {
    const a = 1, 
        b = 2, 
        c = a + b;
    return c;
}

console.log(test());
Jörg W Mittag
  • 363,080
  • 75
  • 446
  • 653
  • 1
    Actually an "*implicit variable definition*" does create a *global* variable, so no `c` is not a local variable. (It should be, of course). – Bergi Oct 28 '18 at 19:22
  • "*since you don't give your function a name, you can use anonymous function literal syntax*" - Huh? `function(){…}` *is* an anonymous function expression already. Did you mean to write "arrow function syntax"? There's no reason to use that here, we don't need to close over `this`. Just make it a `function test() { … }` declaration. – Bergi Oct 28 '18 at 19:24
  • Ugh, you're right. I always forget that ECMAScript is even more insane than I assume. – Jörg W Mittag Oct 28 '18 at 19:33
  • Rewritten. Thanks. – Jörg W Mittag Oct 28 '18 at 19:42
  • You know, just `"use strict";` mode to restore your sanity :-) – Bergi Oct 28 '18 at 19:42
  • I'm actually mostly working with ECMAScript as the configuration language for a hardware device manufactured by my employer; the configuration API for the device uses Promises heavily (actually exclusively, every single function in the API is `async`), and the configuration tool evaluates the scripts by wrapping them into an `await (async () => { })()`, so whatever code I write in the configuration file is *actually* a function body. This drives any editor or linter nuts. E.g. top-level `await` is perfectly legal, because it's actually *not* top-level. – Jörg W Mittag Oct 28 '18 at 19:47
  • Thanks for the responses guys. I have edited my post to elaborate more. I probably should have just posted this in the first place. My mistake. – MattG Oct 28 '18 at 19:51
0

the variables A B and C are of use locally within the function, but it returns the value of C, with just calling the function returns the value, as it says - charlietfl console.log(test()), you can call it that way or:

 var c = test ();
    alert(c) or console.log (c);

Now you can use the name varibale "c" outside the function.