== Why is this an issue?

The `var` statement declares variables that are function-scoped or globally-scoped. `var` declarations are hoisted, meaning declaring a variable anywhere in the code is equivalent to declaring it at the top of the function or the script. 

Even if hoisted, it is still recommended to declare the variable inside the block it is used. This improves readability and maintainability because it makes it clear where the variable is being used. The code then becomes easier to understand and follow, especially for other developers who may be working on the same codebase.

[source,javascript,diff-id=1,diff-type=noncompliant]
----
function doSomething(a, b) {
  if (a > b) {
    var x = a - b;  // Noncompliant: 'x' is used later outside this block
  }

  if (a > 4) {
    console.log(x);
  }

  for (var i = 0; i < m; i++) { // Noncompliant: both loops use same variable
  }

  for (var i = 0; i < n; i++) {
  }

  return a + b;
}
----

When `var` declaration is used outside of a block, the declaration should be done at the uppermost level where it is used. When possible, use `let` or `const`, which allow for block-scoped variables.

[source,javascript,diff-id=1,diff-type=compliant]
----
function doSomething(a, b) {
  var x;

  if (a > b) {
    x = a - b; 
  }

  if (a > 4) {
    console.log(x);
  }

  for (let i = 0; i < m; i++) {
  }

  for (let i = 0; i < n; i++) {
  }


  return a + b;
}
----

== Resources
=== Documentation

* MDN web docs - https://developer.mozilla.org/en-US/docs/Glossary/Scope[Scope]
* MDN web docs - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var[`var`]
* MDN web docs - https://developer.mozilla.org/en-US/docs/Glossary/Hoisting[Hoisting]
* MDN web docs - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const[const]
* MDN web docs - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let[let]

ifdef::env-github,rspecator-view[]

'''
== Implementation Specification
(visible only on this page)

=== Message

Consider moving declaration of 'XXX' as it is referenced outside current binding context.


=== Highlighting

* primary: the variable definition
* secondary: every reference to the variable outside of the current binding context.
** message: 'Outside reference.'


'''
== Comments And Links
(visible only on this page)

=== on 26 Jan 2016, 10:51:24 Elena Vilchik wrote:
\[~ann.campbell.2] WDYT if we change this rule to not function scope but to java-like scopes (function+loops+if)?

Following to this convention will ease transition to ES2015 variables declarations (let and const)

=== on 17 Feb 2016, 09:24:03 Elena Vilchik wrote:
\[~ann.campbell.2] I removed part about functions as it probably will produce FP. See

----
var y;   // OK

function foo(p) {
  if (y) {
    bar(y);
  }
  y = p;
}

for (var j = 1; j < 10; j++) {
  foo(j)
}
----

=== on 18 Feb 2016, 09:49:46 Elena Vilchik wrote:
\[~ann.campbell.2] Looks like after removing this "function" thing this rule has not  much in common with RSPEC-1899. May be we should make it as separate RSPEC, WDYT? (cc [~pierre-yves.nicolas])

endif::env-github,rspecator-view[]
