-2

Consider the following code in JavaScript-

var DEFAULT_RATE=0.01;
var rate=0.04;
function getRate() {
  if(!rate) {
    var rate=DEFAULT_RATE;
  }
  return rate;
}
console.log(`Rate is`,getRate());

The output of the following code is 0.01 My takeaway from this is that vars are hoisted(and declared undefined) to the top of the scope pertaining to the where they are used. In case of let and const, they go into TDZ but that is a different thing entirely.

But I also learnt that var has a global scope. Then var show not allow variable redeclaration.

Isn't the global scope mean the scope containing the entire code? Have I understood it wrongly?

Mike 'Pomax' Kamermans
  • 49,297
  • 16
  • 112
  • 153
LFC
  • 50
  • 5
  • 1
    Note that `var` is essentially legacy syntax, and you want to use `let` and `const` for any new code you write, because they're block-scoped and don't have the quirky scoping gotchas that `var` suffers from. Having said that, can you explain what you based your takeaway on? `var` is function-scoped (and so the variable _declaration_ gets hoisted to the top of a function at parse time, while leaving the _initialization_ where it found it. If that makes it shadow an existing var, too bad) unless declared in global scope, in which case the same thing happens, but globally. – Mike 'Pomax' Kamermans Jan 24 '21 at 18:54
  • Does this answer your question? [Why a variable defined global is undefined?](https://stackoverflow.com/questions/30469755/why-a-variable-defined-global-is-undefined) – Chayim Friedman Jan 24 '21 at 18:57
  • It's an ugly hoisting problem caused by `var rate=DEFAULT_RATE` inside the if block, same as `function getRate() { var rate; if (!rate) {rate=DEFAULT_RATE;} return rate;}`. `getRate` will always return `DEFAULT_RATE`., since the if statement in `getRate` will always be true. – terrymorse Jan 24 '21 at 19:39

2 Answers2

1

When using var to declare variables, the variable can take on either function or global scope. If var is used within a function, it has function scope, if var is used outside of any function, the variable has Global scope.

So, your statement of:

But I also learnt that var has a global scope. Then var show not allow variable redeclaration.

Is actually, not really accurate because it depends on where var is used and redeclaration (more correctly known as variable "hiding") is possible in any smaller scope than the first declaration was made.

When declaring with var, the declaration is hoisted to the top of the scope.

I've written another answer that describes and demonstrates this in detail.

Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
-1

In JavaScript, function declarations are hoisted before var declarations, and assignments are not hoisted.

So the sample code from the question:

var DEFAULT_RATE=0.01;
var rate=0.04;
function getRate() {
  if(!rate) {
    var rate=DEFAULT_RATE;
  }
  return rate;
}

has this effective ordering:

// hoisted function
function getRate() {
  var rate = undefined; // <- hoisted local variable
  if(!rate) { // <- always true
    rate = DEFAULT_RATE; // <- always executed
  }
  return rate; // <- always returns DEFAULT_RATE (0.01)
}

// hoisted vars
var DEFAULT_RATE;
var rate;

// not-hoisted assignments
DEFAULT_RATE = 0.01;
rate = 0.04;

// not-hoisted function call
console.log(`Rate is`,getRate());

Since getRate() contains var rate, the function-scoped rate is hoisted to the beginning of getRate(), with a value of undefined.

Therefore if(!rate) evaluates to if(!undefined), which is always true, and getRate() always returns DEFAULT_RATE (0.01).

terrymorse
  • 6,771
  • 1
  • 21
  • 27