1

Code

function hi() {
    myvar = 'local variable';
}
console.log(myvar);

Output: ReferenceError: myvar is not defined

According to my understanding, javascript goes line by line, examines the variables and their scope. Keeping that in mind shouldn't the following print 'undefined', as myvar exists in global scope?

  • 1
    Possible duplicate of [Define global variable in a JavaScript function](https://stackoverflow.com/questions/5786851/define-global-variable-in-a-javascript-function) – Zoe Edwards Jun 13 '18 at 10:22
  • 1
    @musefan it **doesn't** print `undefined` actually. The question is why is it not logging `undefined` (instead he has an error message) – Ivan Jun 13 '18 at 10:22
  • Also be aware implicit global's will throw this error when using strict mode. – ste2425 Jun 13 '18 at 10:24
  • 2
    @musefan his question clearly states that he wants to understand why he received `Output: ReferenceError: myvar is not defined` as opposed to `undefined` – ed' Jun 13 '18 at 10:25
  • 1
    @musefan, when you're saying "It prints undefined because" that means you didn't try it out. The code doesn't print `undefined` at all – Ivan Jun 13 '18 at 10:25
  • @musefan all right, no problem – Ivan Jun 13 '18 at 10:31

4 Answers4

5

No it shouldn't, for it to print undefined you need to first define it in a global scope.

The fact that you are assigning some value to that variable inside of a function doesn't mean anything until the function itself is executed.

var myvar;

function hi() {
    myvar = 'local variable';
}
console.log(myvar);

If you omit that var myvar; line and and execute hi function before you do the console.log, you will get "local variable" as a result because that function creates an implicit global binding.

To check this, simply use strict mode and you will get error instead of the result above because strict mode prevents implicit globals.

"use strict";

function hi() {
    myvar = 'local variable';
}

hi();

console.log(myvar);
Matus Dubrava
  • 13,637
  • 2
  • 38
  • 54
  • I think it is in global scope already. If you call function hi, before console.log(), it prints 'local variable'. – Prabhat Doongarwal Jun 13 '18 at 10:36
  • @PrabhatDoongarwal check now. – Matus Dubrava Jun 13 '18 at 10:41
  • So, js first checks for function calls, before processing code in that function? – Prabhat Doongarwal Jun 13 '18 at 10:46
  • As long as you don't call `hi` js will not look at what's in the function's scope. If I'm not mistaken. – Ivan Jun 13 '18 at 10:49
  • Are you sure or is it your hypothesis? – Prabhat Doongarwal Jun 13 '18 at 10:51
  • @PrabhatDoongarwal That is correct, js checks for function definitions then for variable definitions and then it starts executing code line by line. But `function hi() {}` is just a function definition not a call that would be executed. To execute it you need to call it in a one way or the other. – Matus Dubrava Jun 13 '18 at 10:52
  • You said it checks for function definition, but not for call. So, it should not mater if call is being made or not. – Prabhat Doongarwal Jun 13 '18 at 10:57
  • @PrabhatDoongarwal It does because by checking for function definition JS only registers that function name so that you can call it anywhere inside of a scope in which it was defined without getting an error. But it does not process the body of a function until that function is called. – Matus Dubrava Jun 13 '18 at 11:00
  • Ok. I get it. You should add this point to the answer. Thanks. Also, can you guide me towards some docs that mentions this point, so that I can understand the whole process of js code processing. – Prabhat Doongarwal Jun 13 '18 at 11:05
  • @PrabhatDoongarwal [You don't know JS: Scope and closures](https://maximdenisov.gitbooks.io/you-don-t-know-js/content/scope_&_closures/intro.html) is a small but great book, readable online and you will find answer to anything mentioned here and much more, regarding scoping rules, hoisting etc. – Matus Dubrava Jun 13 '18 at 11:08
2

The problem: myvar throws a ReferenceError

function hi() {
  myvar = 'local variable';
}
console.log(myvar);

I understand you thought you would get undefined.

In the above code myvar hasn't been defined outside the function's scope. So when calling console.log(myvar) it will throw an error. You can ignore the function's declaration for this part, it's as if you had:

console.log(myvar)

Solution: set myvar outside of the function's scope

So you need to define your variable before logging it, for example:

var myvar;

function hi() {
  myvar = 'local variable';
}
console.log(myvar);

This will ensure that myvar is defined here

  • outside the function's scope: it doesn't have any value so it's undefined

  • in the function's scope: it is set to a string


More on global variables

As you haven't added the var operator before myvar = 'local variable'; you have essentially accessed the global variable myvar. So by calling hi() you will change the value of myvar outside of the function's scope:

var myvar;

function hi() {
  myvar = 'local variable';
}

console.log(myvar);
hi();
console.log(myvar);
Ivan
  • 34,531
  • 8
  • 55
  • 100
2

As found in the MDN docs

You can declare a variable in three ways:

  • With the keyword var. For example, var x = 42. This syntax can be used to declare both local and global variables.

  • By simply assigning it a value. For example, x = 42. If this form is used outside of a function, it declares a global variable. It generates a strict JavaScript warning. You shouldn't use this variant.

  • With the keyword let. For example, let y = 13. This syntax can be used to declare a block-scope local variable. See Variable scope below.

Your function will work, because it satisfies method #2, declaring a variable by assigning it a value.

The console.log(myvar) will not work as myvar was never declared through any of the 3 means mentioned above. As such, you get a ReferenceError.

According to my understanding, javascript goes line by line, examines the variables and their scope. Keeping that in mind shouldn't the following print 'undefined', as myvar exists in global scope?

No, the function was not called, and as such the code inside it was not run, and so the variable was never created. If you had myvar = 'local variable'; outside of the function, it will work.

ed'
  • 1,815
  • 16
  • 30
  • So, js checks for function call, before processing the code in a function? – Prabhat Doongarwal Jun 13 '18 at 11:02
  • Yes of course, it won't run functions for you unless you ask it to. Just to clarify I don't mean that if you call the function, the script will be parsed the script differently. The only difference is that by calling the function, the variable gets defined, as assigning a value to a variable also declares it (in javascript) – ed' Jun 13 '18 at 11:18
  • There is difference in executing and registering variables and their scope. Consider the following [code](https://ideone.com/sC8eUg). It prints undefined, even before the variable is declared. – Prabhat Doongarwal Jun 13 '18 at 11:28
  • But, I guess it could be different for functions. – Prabhat Doongarwal Jun 13 '18 at 11:29
  • No, you have added a new difference to the scenario called `Variable Hoisting` there which you are overlooking. Whilst it may *appear* that you have used a variable before it was defined, all `var` declarations are "hoisted" to the top of the scope by the JS parser. More info here: https://developer.mozilla.org/en-US/docs/Glossary/Hoisting – ed' Jun 13 '18 at 11:30
  • Therefore, what you actually wrote as far as the parser is concerned is this: https://ideone.com/q8pIf9 – ed' Jun 13 '18 at 11:32
  • Nice point. I started from hoisting and ended up here. I never considered that could have been the case. – Prabhat Doongarwal Jun 13 '18 at 11:52
0

This is because the variable scope is local to the function. try declaring the variable outside first.

var myvar;
function hi() {
  myvar = 'local variable';
}
console.log(myvar);
  • I don't think it is local to the function. Because after you call the function then you are able to access it in the global scope. It just seems for some reason it doesn't set it to global scope until after the function call – musefan Jun 13 '18 at 10:34
  • @musefan, Indeed unless you use `var` the variable `myvar` will **not** be local to `hi` – Ivan Jun 13 '18 at 10:39