By lYriCAlsSH

2009-02-01 08:27:19 8 Comments

What is the scope of variables in javascript? Do they have the same scope inside as opposed to outside a function? Or does it even matter? Also, where are the variables stored if they are defined globally?


@Ahmed KhaShaba 2020-05-25 16:11:42

I really like the accepted answer but I want to add this:

Scope collects and maintains a look-up list of all the declared identifiers (variables), and enforces a strict set of rules as to how these are accessible to currently executing code.

Scope is a set of rules for looking up variables by their identifier name.

  • If a variable cannot be found in the immediate scope, Engine consults the next outer containing scope, continuing until is found or until the outermost (a.k.a., global) scope has been reached.
  • Is the set of rules that determines where and how a variable (identifier) can be looked up. This look-up may be for the purposes of assigning to the variable, which is an LHS (left-hand-side) reference, or it may be for the purposes of retrieving its value, which is an RHS (righthand-side) reference.
  • LHS references result from assignment operations. Scope-related assignments can occur either with the = operator or by passing arguments to (assign to) function parameters.
  • The JavaScript engine first compiles code before it executes, and in so doing, it splits up statements like var a = 2; into two separate steps: 1st. First, var a to declare it in that scope. This is performed at the beginning, before code execution. 2nd. Later, a = 2 to look up the variable (LHS reference) and assign to it if found.
  • Both LHS and RHS reference look-ups start at the currently executing scope, and if need be (that is, they don’t find what they’re looking for there), they work their way up the nested scope, one scope (floor) at a time, looking for the identifier, until they get to the global (top floor) and stop, and either find it, or don’t. Unfulfilled RHS references result in ReferenceError being thrown. Unfulfilled LHS references result in an automatic, implicitly created global of that name (if not in Strict Mode), or a ReferenceError (if in Strict Mode).
  • scope consists of a series of “bubbles” that each act as a container or bucket, in which identifiers (variables, functions) are declared. These bubbles nest neatly inside each other, and this nesting is defined at author time.

@Triptych 2009-02-01 08:58:50


JavaScript has lexical (also called static) scoping and closures. This means you can tell the scope of an identifier by looking at the source code.

The four scopes are:

  1. Global - visible by everything
  2. Function - visible within a function (and its sub-functions and blocks)
  3. Block - visible within a block (and its sub-blocks)
  4. Module - visible within a module

Outside of the special cases of global and module scope, variables are declared using var (function scope), let (block scope) and const (block scope). Most other forms of identifier declaration have block scope in strict mode.


Scope is the region of the codebase over which an identifier is valid.

A lexical environment is a mapping between identifier names and the values associated with them.

Scope is formed of a linked nesting of lexical environments, with each level in the nesting corresponding to a lexical environment of an ancestor execution context.

These linked lexical environments form a scope "chain". Identifier resolution is the process of searching along this chain for a matching identifier.

Identifier resolution only occurs in one direction: outwards. In this way, outer lexical environments cannot "see" into inner lexical environments.

There are three pertinent factors in deciding the scope of an identifier in JavaScript:

  1. How an identifier was declared
  2. Where an identifier was declared
  3. Whether you are in strict mode or non-strict mode

Some of the ways identifiers can be declared:

  1. var, let and const
  2. Function parameters
  3. Catch block parameter
  4. Function declarations
  5. Named function expressions
  6. Implicitly defined properties on the global object (ie. missing out var in non-strict mode)
  7. import statements
  8. eval

Some of the locations identifiers can be declared:

  1. Global context
  2. Function body
  3. Ordinary block
  4. The top of a control structure (eg. loop, if, while etc)
  5. Control structure body
  6. Modules

Declaration Styles


Identifiers declared using var have function scope, apart from when they are declared directly in the global context, in which case they are added as properties on the global object and have global scope. There are separate rules for their use in eval functions.

let and const

Identifiers declared using let and const have block scope, apart from when they are declared directly in the global context, in which case they have global scope.

Note: let, const and var are all hoisted. This means that their logical position of definition is the top of their enclosing scope (block or function). However, variables declared useing let and const cannot be read or assigned to until control has passed the point of declaration in the source code. The interim period is known as the temporal dead zone.

function f() {
    function g() {
    let x = 1
f() // 1 because x is hoisted even though declared with `let`!

Function parameter names

Function parameter names are scoped to the function body. Note that there is a slight complexity to this. Functions declared as default arguments close over the parameter list, and not the body of the function.

Function declarations

Function declarations have block scope in strict mode and function scope in non-strict mode. Note: non-strict mode is a complicated set of emergent rules based on the quirky historical implementations of different browsers.

Named function expressions

Named function expressions are scoped to themselves (eg. for the purpose of recursion).

Implicitly defined properties on the global object

In non-strict mode, implicitly defined properties on the global object have global scope, because the global object sits at the top of the scope chain. In strict mode these are not permitted.


In eval strings, variables declared using var will be placed in the current scope, or, if eval is used indirectly, as properties on the global object.


The following will throw a ReferenceError because the namesx, y and z have no meaning outside of the function f.

function f() {
    var x = 1
    let y = 1
    const z = 1
console.log(typeof x) // undefined (because var has function scope!)
console.log(typeof y) // undefined (because the body of the function is a block)
console.log(typeof z) // undefined (because the body of the function is a block)

The following will throw a ReferenceError for y and z, but not for x, because the visibility of x is not constrained by the block. Blocks that define the bodies of control structures like if, for and while, behave similarly.

    var x = 1
    let y = 1
    const z = 1
console.log(x) // 1
console.log(typeof y) // undefined because `y` has block scope
console.log(typeof z) // undefined because `z` has block scope

In the following, x is visible outside of the loop because var has function scope:

for(var x = 0; x < 5; ++x) {}
console.log(x) // 5 (note this is outside the loop!)

...because of this behavior you need to be careful about closing over variables declared using var in loops. There is only one instance of variable x declared here, and it sits logically outside of the loop.

The following prints 5, five times, and then prints 5 for an sixth time for the console.log outside the loop:

for(var x = 0; x < 5; ++x) {
    setTimeout(() => console.log(x)) // closes over the `x` which is logically positioned at the top of the enclosing scope, above the loop
console.log(x) // note: visible outside the loop

The following prints undefined because x is block-scoped. The callbacks are run one by one asynchronously. New behavior for let variables means that each anonymous function closed over a different variable named x (unlike it would have done with var), and so integers 0 through 4 are printed.:

for(let x = 0; x < 5; ++x) {
    setTimeout(() => console.log(x)) // `let` declarations are re-declared on a per-iteration basis, so the closures capture different variables
console.log(typeof x) // undefined

The following will NOT throw a ReferenceError because the visibility of x is not constrained by the block; it will, however, print undefined because the variable has not been initialised (because of the if statement).

if(false) {
    var x = 1
console.log(x) // here, `x` has been declared, but not initialised

A variable declared at the top of a for loop using let is scoped to the body of the loop:

for(let x = 0; x < 10; ++x) {} 
console.log(typeof x) // undefined, because `x` is block-scoped

The following will throw a ReferenceError because the visibility of x is constrained by the block:

if(false) {
    let x = 1
console.log(typeof x) // undefined, because `x` is block-scoped

Variables declared using var, let or const are all scoped to modules:

// module1.js

var x = 0
export function f() {}


import f from 'module1.js'

console.log(x) // throws ReferenceError

The following will declare a property on the global object, because variables declared using var within the global context, are added as properties to the global object:

var x = 1
console.log(window.hasOwnProperty('x')) // true

let and const in the global context do not add properties to the global object, but still have global scope:

let x = 1
console.log(window.hasOwnProperty('x')) // false

Function parameters can be considered to be declared in the function body:

function f(x) {}
console.log(typeof x) // undefined, because `x` is scoped to the function

Catch block parameters are scoped to the catch-block body:

try {} catch(e) {}
console.log(typeof e) // undefined, because `e` is scoped to the catch block

Named function expressions are scoped only to the expression itself:

(function foo() { console.log(foo) })()
console.log(typeof foo) // undefined, because `foo` is scoped to its own expression

In non-strict mode, implicitly defined properties on the global object are globally scoped. In strict mode you get an error.

x = 1 // implicitly defined property on the global object (no "var"!)

console.log(x) // 1
console.log(window.hasOwnProperty('x')) // true

In non-strict mode, function declarations have function scope. In strict mode they have block scope.

'use strict'
    function foo() {}
console.log(typeof foo) // undefined, because `foo` is block-scoped

How it works under the hood

Scope is defined as the lexical region of code over which an identifier is valid.

In JavaScript, every function-object has a hidden [[Environment]] reference that is a reference to the lexical environment of the execution context (stack frame) within which it was created.

When you invoke a function, the hidden [[Call]] method is called. This method creates a new execution context and establishes a link between the new execution context and the lexical environment of the function-object. It does this by copying the [[Environment]] value on the function-object, into an outer reference field on the lexical environment of the new execution context.

Note that this link between the new execution context and the lexical environment of the function object is called a closure.

Thus, in JavaScript, scope is implemented via lexical environments linked together in a "chain" by outer references. This chain of lexical environments is called the scope chain, and identifier resolution occurs by searching up the chain for a matching identifier.

Find out more.

@Triptych 2009-02-01 09:08:41

Not even close to being comprehensive, but this is maybe the must-know set of Javascript scope tricks one needs to effectively even READ modern javascript.

@lYriCAlsSH 2009-02-01 09:15:41

Considering your remark on 'ranking', i guess i'll start reading more on this sort of thing. But its not as bad as i thought, i understood the logic behind it rather well. Although, about the object properties, if i declare it globally will it be referenced by object.prototype?

@000 2011-02-10 13:49:03

Thanks, what i want to add is if you file is undefined try using new Array or new String an so on

@marta.joed 2012-07-10 18:23:20

Very helpful! I always keep in mind that JavaScript is NOT JAVA, especially when it comes to scope! Remember Javascript's functional heritage any time you have to think about scope

@RobG 2012-09-10 00:35:18

A highly rated answer, not sure why. It's just a bunch of examples without proper explanation, then seems to confuse prototype inheritance (i.e. property resolution) with the scope chain (i.e. variable resolution). A comprehensive (and accurate) explanation of scope and property resolution is in the comp.lang.javascript FAQ notes.

@Triptych 2012-09-10 05:34:39

@RobG It is highly rated because it is useful and comprehensible to a wide range of programmers, minor catachresis notwithstanding. The link you have posted, while useful to some professionals, is incomprehensible to most people writing Javascript today. Feel free to fix any nomenclature issues by editing the answer.

@RobG 2012-09-10 07:02:36

@triptych—I only edit answers to fix minor things, not major. Changing "scope" to "property" will fix the error, but not the issue of mixing inheritance and scope without a very clear distinction.

@Igor Mukhin 2013-06-07 06:58:55

Another interesting case: for (var n = 4; false; ) { } alert(n); will output "4" (not "undefined" as you may expect);

@Chris S 2013-06-12 23:28:45

If you define a variable in the outer scope, and then have an if statement define a variable inside the function with the same name, even if that if branch isn't reached it is redefined. An example -

@GibboK 2013-10-30 21:18:53

Try out this learning quiz, it can help to understand variable scope in JS

@Kevin Meredith 2014-01-01 04:23:05

@Triptych (thanks). For this fiddle (, does a 1 print out since a within function Seven is, by default, global?

@Muhammad Umer 2014-04-15 18:51:07

is this not true for functions...if i define function inside a function the this still refers to window object but it's accessible in windows object.

@rkulla 2014-05-20 20:38:57

The closure example isn't the big picture because it's not required to have a local variable declaration in order to close over a variable. In example 5 you could put the 'var foo = 6' outside of all functions and still close over it.

@blgt 2014-07-02 15:22:40

Re. the last edit (example 8): This is exactly the same behaviour as example 2, function 2. You're simply attempting to use a local variable before you've assigned a value to it.

@RobG 2014-07-30 07:08:09

@MuhammadUmer—each execution context (e.g. global, function, eval) has its own this parameter that is set by how the function is called or the use of bind. It has nothing to do with where or how the function is defined.

@dz210 2015-12-22 20:57:29

Can someone explain the last one, #9? Shouldn't the catch variable e shadow the original variable and print out the error?

@thetrystero 2016-01-18 08:13:25

why is #4 called "object property". did you mean "method"? but there is not object anywhere in that example. I see that "this" === "global" but this has nothing to do with objects. can someone please explain? EDIT: I think you mean to use it as a constructor, as in var b = new five() not to invoke it on its own. is that right? in that case i see that "this" === "b". so I guess b is the object. but it still has no properties attached to it.

@devnull 2016-10-01 21:45:28

5. Closure example is not correct. Unless six() is called, the alert doesn't get executed.

@Triptych 2016-10-03 12:52:00

@devnull - did you try it? It's correct as written (the function self-executes).

@Huang Chao 2017-04-12 07:14:32

@Triptych In point 6, // Won't get reached, because 'a' is set in the constructor above. seven.prototype.a = -1; However, I think it's not that the statement won't get reached, but even although it executes, the this.a = 7 in constructor function will override the value of a to 7 because this.a = 7 executes after copying values from prototype.

@overexchange 2018-04-24 15:48:24

If the scoping rules are not precise/concise using var keyword, then do not use it. Use const or let keyword

@foxt7ot 2018-06-22 13:23:42

@Triptych Appreciate your answer but don't you think that this answer needs to be updated as with the advent of let block level of scope is introduced in javascript and in point 3 you'd mentioned that "No such thing as block scope in JavaScript ". Please check this blog as well…

@Ayush Jain 2019-02-27 08:03:59

Basically, Javascript uses Lexical Scoping (Also known as Static Scoping) which says a variable defined in one part of your program may not be accessible to the other parts of the program. A variable declared in this fashion is sometimes called as a private variable. The opposite to this is Dynamic Scoping which is not at all used by Javascript.…

@iAmOren 2020-07-01 07:10:04

The question was about vars as in "variables"! You have included crap like let and const that destroy javascript and users of those are writing javastrict... var rules!

@John Slegers 2016-02-23 18:51:35

Old school JavaScript

Traditionally, JavaScript really only has two types of scope :

  1. Global Scope : Variables are known throughout the application, from the start of the application (*)
  2. Functional Scope : Variables are known within the function they are declared in, from the start of the function (*)

I will not elaborate on this, since there are already many other answers explaining the difference.

Modern JavaScript

The most recent JavaScript specs now also allow a third scope :

  1. Block Scope : Identifiers are "known" from the top of the scope they are declared within, but they cannot be assigned to or dereferenced (read) until after the line of their declaration. This interim period is called the "temporal dead zone."

How do I create block scope variables?

Traditionally, you create your variables like this :

var myVariable = "Some text";

Block scope variables are created like this :

let myVariable = "Some text";

So what is the difference between functional scope and block scope?

To understand the difference between functional scope and block scope, consider the following code :

// i IS NOT known here
// j IS NOT known here
// k IS known here, but undefined
// l IS NOT known here

function loop(arr) {
    // i IS known here, but undefined
    // j IS NOT known here
    // k IS known here, but has a value only the second time loop is called
    // l IS NOT known here

    for( var i = 0; i < arr.length; i++ ) {
        // i IS known here, and has a value
        // j IS NOT known here
        // k IS known here, but has a value only the second time loop is called
        // l IS NOT known here

    // i IS known here, and has a value
    // j IS NOT known here
    // k IS known here, but has a value only the second time loop is called
    // l IS NOT known here

    for( let j = 0; j < arr.length; j++ ) {
        // i IS known here, and has a value
        // j IS known here, and has a value
        // k IS known here, but has a value only the second time loop is called
        // l IS NOT known here

    // i IS known here, and has a value
    // j IS NOT known here
    // k IS known here, but has a value only the second time loop is called
    // l IS NOT known here


for( var k = 0; k < arr.length; k++ ) {
    // i IS NOT known here
    // j IS NOT known here
    // k IS known here, and has a value
    // l IS NOT known here

for( let l = 0; l < arr.length; l++ ) {
    // i IS NOT known here
    // j IS NOT known here
    // k IS known here, and has a value
    // l IS known here, and has a value


// i IS NOT known here
// j IS NOT known here
// k IS known here, and has a value
// l IS NOT known here

Here, we can see that our variable j is only known in the first for loop, but not before and after. Yet, our variable i is known in the entire function.

Also, consider that block scoped variables are not known before they are declared because they are not hoisted. You're also not allowed to redeclare the same block scoped variable within the same block. This makes block scoped variables less error prone than globally or functionally scoped variables, which are hoisted and which do not produce any errors in case of multiple declarations.

Is it safe to use block scope variables today?

Whether or not it is safe to use today, depends on your environment :

  • If you're writing server-side JavaScript code (Node.js), you can safely use the let statement.

  • If you're writing client-side JavaScript code and use a browser based transpiler (like Traceur or babel-standalone), you can safely use the let statement, however your code is likely to be anything but optimal with respect to performance.

  • If you're writing client-side JavaScript code and use a Node based transpiler (like the traceur shell script or Babel), you can safely use the let statement. And because your browser will only know about the transpiled code, performance drawbacks should be limited.

  • If you're writing client-side JavaScript code and don't use a transpiler, you need to consider browser support.

    These are some browsers that don't support let at all :

    • Internet explorer 10 and below
    • Firefox 43 and below
    • Safari 9 and below
    • Android browser 4 and below
    • Opera 27 and below
    • Chome 40 and below
    • ANY version of Opera Mini & Blackberry Browser

enter image description here

How to keep track of browser support

For an up-to-date overview of which browsers support the let statement at the time of your reading this answer, see this Can I Use page.

(*) Globally and functionally scoped variables can be initialized and used before they are declared because JavaScript variables are hoisted. This means that declarations are always much to the top of the scope.

@Oriol 2016-08-30 04:48:19

"IS NOT known" is misleading, because the variable is declared there due to hoisting.

@zakir 2018-01-24 16:35:25

The above example is misleading, variables 'i' and 'j' are not known outside the block. 'Let' variables has scope only in that particular block not outside of the block. Let has other advantages as well, you can't redeclare the variable again and it's hold the lexical scope.

@John Slegers 2018-01-25 15:28:15

@Oriol : Finally got to improving my answer and address hoisting. Thanks for pointing out my answer needed improvement. I made a few other improvements as well.

@John Slegers 2018-01-25 15:31:42

@zakir : Variables declared with let (block scope) are not known outside the block they're declared in. Variables declared with var (functional or global scope) are known outside the block they're declared in buth not known outside the function they're declared in, if they're declared inside a function. I thought I was pretty clear on that. Anyway, I added more info on differences in behavior with respect to hoisting and with respect to multiple declarations of the same variable within the same scope. Thanks for pointing that out.

@Jon Schneider 2018-03-06 20:57:23

This was helpful, thanks! I think it would be even more helpful to be specific about what you mean by "Modern JavaScript" and "Old school JavaScript"; I think these correspond to ECMAScript 6 / ES6 / ECMAScript 2015, and to earlier versions, respectively?

@John Slegers 2018-03-06 22:25:51

@JonSchneider : Correct! Where I say "old school JavaScript", I'm ineed talking about ECMAScript 5 and where I'm refering to "modern JavaScript", I'm taking about ECMAScript 6 (aka ECMAScript 2015). I didn't think it was really that important to go into detail here, though, as most people just want to know (1) what's the difference between block scope and functional scope, (2) what browsers support block scope and (3) whether it's safe to use block scope today for whatever project they're working on. So I focused my answer on addressing those issues.

@John Slegers 2018-03-06 22:27:59

@JonSchneider : (continued) Nevertheless, I just added a link to a Smashing Magazine article on ES6 / ES2015 for those who want to learn more about which features have been added to JavaScript during the last couple of years... of anyone else who might be wondering what I mean with "modern JavaScript".

@iAmOren 2020-07-01 07:19:18

Question about vars. "const" and "let" are a crappy subtraction from/burden on- javascript.

@CertainPerformance 2019-12-31 02:50:45

A very common issue not described yet that front-end coders often run into is the scope that is visible to an inline event handler in the HTML - for example, with

<button onclick="foo()"></button>

The scope of the variables that an on* attribute can reference must be either:

  • global (working inline handlers almost always reference global variables)
  • a property of the document (eg, querySelector as a standalone variable will point to document.querySelector; rare)
  • a property of the element the handler is attached to (like above; rare)

Otherwise, you'll get a ReferenceError when the handler is invoked. So, for example, if the inline handler references a function which is defined inside window.onload or $(function() {, the reference will fail, because the inline handler may only reference variables in the global scope, and the function is not global:

window.addEventListener('DOMContentLoaded', () => {
  function foo() {
    console.log('foo running');
<button onclick="foo()">click</button>

Properties of the document and properties of the element the handler is attached to may also be referenced as standalone variables inside inline handlers because inline handlers are invoked inside of two with blocks, one for the document, one for the element. The scope chain of variables inside these handlers is extremely unintuitive, and a working event handler will probably require a function to be global (and unnecessary global pollution should probably be avoided).

Since the scope chain inside inline handlers is so weird, and since inline handlers require global pollution to work, and since inline handlers sometimes require ugly string escaping when passing arguments, it's probably easier to avoid them. Instead, attach event handlers using Javascript (like with addEventListener), rather than with HTML markup.

function foo() {
  console.log('foo running');
document.querySelector('.my-button').addEventListener('click', foo);
<button class="my-button">click</button>

On a different note, unlike normal <script> tags, which run on the top level, code inside ES6 modules runs in its own private scope. A variable defined at the top of a normal <script> tag is global, so you can reference it in other <script> tags, like this:

const foo = 'foo';

But the top level of an ES6 module is not global. A variable declared at the top of an ES6 module will only be visible inside that module, unless the variable is explicitly exported, or unless it's assigned to a property of the global object.

<script type="module">
const foo = 'foo';
// Can't access foo here, because the other script is a module
console.log(typeof foo);

The top level of an ES6 module is similar to that of the inside of an IIFE on the top level in a normal <script>. The module can reference any variables which are global, and nothing can reference anything inside the module unless the module is explicitly designed for it.

@Willem van der Veen 2018-09-30 09:23:31

ES5 and earlier:

Variables in Javascript were initially (pre ES6) lexically function scoped. The term lexically scoped means that you can see the scope of the variables by 'looking' at the code.

Every variable declared with the var keyword is scoped to the function. However, if other function are declared within that function those functions will have access to the variables of the outer functions. This is called a scope chain. It works in the following manner:

  1. When a function look to resolve a variable value it first looks at its own scope. This is the function body, i.e. everything between curly brackets {} (except for variables inside other functions which are in this scope).
  2. If it cannot find the variable inside the the function body it will climb up to the chain and look at the variable scope in the function in where the function was defined. This is what is meant with lexical scope, we can see in the code where this function was defined and thus can determine the scope chain by merely looking at the code.


// global scope
var foo = 'global';
var bar = 'global';
var foobar = 'global';

function outerFunc () {
 // outerFunc scope
 var foo = 'outerFunc';
 var foobar = 'outerFunc';
 function innerFunc(){
 // innerFunc scope
  var foo = 'innerFunc';


What happens when we are trying to log the variables foo, bar, and foobar to the console is the following:

  1. We try to log foo to the console, foo can be found inside the function innerFunc itself. Therefore, the value of foo is resolved to the string innerFunc.
  2. We try to log bar to the console, bar cannot be found inside the function innerFunc itself. Therefore, we need to climb the scope chain. We first look in the outer function in which the function innerFunc was defined. This is the function outerFunc. In the scope of outerFunc we can find the variable bar, which holds the string 'outerFunc'.
  3. foobar cannot be found in innerFunc. . Therefore, we need to climb the scope chain to the innerFunc scope. It also cannot be found here, we climb another level to the global scope (i.e. the outermost scope). We find the variable foobar here which holds the string 'global'. If it wouldnot have found the variable after climbing the scope chain the JS engine would throw a referenceError.

ES6 (ES 2015) and older:

The same concepts of lexically scope and scopechain still apply in ES6. However a new ways to declare variables were introduced. There are the following:

  • let: creates a block scoped variable
  • const: creates a block scoped variable which has to be initialized and cannot be reassigned

The biggest difference between var and let/const is that var is function scoped whereas let/const are block scoped. Here is an example to illustrate this:

let letVar = 'global';
var varVar = 'global';

function foo () {
  if (true) {
    // this variable declared with let is scoped to the if block, block scoped
    let letVar = 5;
    // this variable declared with let is scoped to the function block, function scoped
    var varVar = 10;


In the above example letVar logs the value global because variables declared with let are block scoped. They cease to exist outside their respective block, so the variable can't be accessed outside the if block.

@Davaakhuu Erdenekhuu 2018-02-09 15:37:12

ECMAScript 6 introduced the let and const keywords. These keywords can be used in place of the var keyword. Contrary to the var keyword, the let and const keywords support the declaration of local scope inside block statements.

var x = 10
let y = 10
const z = 10
  x = 20
  let y = 20
  const z = 20
    x = 30
    // x is in the global scope because of the 'var' keyword
    let y = 30
    // y is in the local scope because of the 'let' keyword
    const z = 30
    // z is in the local scope because of the 'const' keyword
    console.log(x) // 30
    console.log(y) // 30
    console.log(z) // 30
  console.log(x) // 30
  console.log(y) // 20
  console.log(z) // 20

console.log(x) // 30
console.log(y) // 10
console.log(z) // 10

@iAmOren 2020-07-01 07:23:02

const and let are not part of the question. why bring them up? personally, they don't belong in javascript...

@Vivek Mehta 2017-12-15 05:31:29

In EcmaScript5, there are mainly two scopes, local scope and global scope but in EcmaScript6 we have mainly three scopes, local scope, global scope and a new scope called block scope.

Example of block scope is :-

for ( let i = 0; i < 10; i++)
statement2...// inside this scope we can access the value of i, if we want to access the value of i outside for loop it will give undefined.

@Gibolt 2017-09-26 20:23:11

Modern Js, ES6+, 'const' and 'let'

You should be using block scoping for every variable you create, just like most other major languages. var is obsolete. This makes your code safer and more maintainable.

const should be used for 95% of cases. It makes it so the variable reference can't change. Array, object, and DOM node properties can change and should likely be const.

let should be be used for any variable expecting to be reassigned. This includes within a for loop. If you ever change value beyond initialization, use let.

Block scope means that the variable will only be available within the brackets in which it is declared. This extends to internal scopes, including anonymous functions created within your scope.

@iAmOren 2020-07-01 07:20:37

question about var. "const" and "let" = the destroyers of javascript, are not in the question and should not be in javascript...

@Gibolt 2020-07-01 16:51:25

Your opinion does not change the validity of the answer. Question is about scoping. const and let are the modern replacements for var which define scope. Neither existed when the question was asked

@Abdur Rahman 2017-11-01 09:16:18

In JavaScript there are two types of scope:

  • Local scope
  • Global scope

The Below function has a local scope variable carName. And this variable is not accessible from outside of the function.

function myFunction() {
    var carName = "Volvo";
    // code here can use carName

The Below Class has a Global scope variable carName. And this variable is accessible from everywhere in the class.

class {

    var carName = " Volvo";

    // code here can use carName

    function myFunction() {
        // code here can use carName 

@iAmOren 2020-07-01 07:24:31

const and let are not in the question. why would you bring them up? the question was about vars... const and let are annoying and destroying javascript.

@mrmaclean89 2017-09-16 22:35:07

My understanding is that there are 3 scopes: global scope, available globally; local scope, available to an entire function regardless of blocks; and block scope, only available to the block, statement, or expression on which it was used. Global and local scope are indicated with the keyword 'var', either within a function or outside, and block scope is indicated with the keyword 'let'.

For those that believe there is only global and local scope, please explain why Mozilla would have an entire page describing the nuances of block scope in JS.

@James Drinkard 2016-03-30 13:33:04

Just to add to the other answers, scope is a look-up list of all the declared identifiers (variables), and enforces a strict set of rules as to how these are accessible to currently executing code. This look-up may be for the purposes of assigning to the variable, which is an LHS (lefthand-side) reference, or it may be for the purposes of retrieving its value, which is an RHS (righthand-side) reference. These look-ups are what the JavaScript engine is doing internally when it's compiling and executing the code.

So from this perspective, I think that a picture would help that I found in the Scopes and Closures ebook by Kyle Simpson:


Quoting from his ebook:

The building represents our program’s nested scope ruleset. The first floor of the building represents your currently executing scope, wherever you are. The top level of the building is the global scope. You resolve LHS and RHS references by looking on your current floor, and if you don’t find it, taking the elevator to the next floor, looking there, then the next, and so on. Once you get to the top floor (the global scope), you either find what you’re looking for, or you don’t. But you have to stop regardless.

One thing of note that is worth mentioning, "Scope look-up stops once it finds the first match".

This idea of "scope levels" explains why "this" can be changed with a newly created scope, if it's being looked up in a nested function. Here is a link that goes into all these details, Everything you wanted to know about javascript scope

@Jhankar Mahbub 2014-06-24 14:12:58

Global Scope :

Global variables are exactly like global stars (Jackie Chan, Nelson Mandela). You can access them (get or set the value), from any part of your application. Global functions are like global events (New Year, Christmas). You can execute (call) them from any part of your application.

//global variable
var a = 2;

//global function
function b(){
   console.log(a);  //access global variable

Local Scope :

If you are in the USA, you may know Kim Kardashian, infamous celebrity ( she somehow manages to make the tabloids). But people outside of the USA will not recognize her. She is a local star, bound to her territory.

Local variables are like local stars. You can only access them (get or set the value) inside the scope. A local function is like local events - you can execute only (celebrate) inside that scope. If you want to access them from outside of the scope, you will get a reference error

function b(){
   var d = 21; //local variable

   function dog(){  console.log(a); }
     dog(); //execute local function

 console.log(d); //ReferenceError: dddddd is not defined    

Check this article for in-depth understanding of scope

@A. Randhawa 2015-09-30 20:46:45

There are two types of scopes in JavaScript.

  1. Global scope: variable which is announced in global scope can be used anywhere in the program very smoothly. For example:

    var carName = " BMW";
    // code here can use carName
    function myFunction() {
         // code here can use carName 
  2. Functional scope or Local scope: variable declared in this scope can be used in its own function only. For example:

    // code here can not use carName
    function myFunction() {
       var carName = "BMW";
       // code here can use carName

@jackbean818 2015-10-29 16:12:19

There are ALMOST only two types of JavaScript scopes:

  • the scope of each var declaration is associated with the most immediately enclosing function
  • if there is no enclosing function for a var declaration, it is global scope

So, any blocks other than functions do not create a new scope. That explains why for-loops overwrite outer scoped variables:

var i = 10, v = 10;
for (var i = 0; i < 5; i++) { var v = 5; }
console.log(i, v);
// output 5 5

Using functions instead:

var i = 10, v = 10;
$.each([0, 1, 2, 3, 4], function(i) { var v = 5; });
// output 10 10

In the first example, there was no block scope, so the initially declared variables were overwritten. In the second example, there was a new scope due to the function, so the initially declared variables were SHADOWED, and not overwritten.

That's almost all you need to know in terms of JavaScript scoping, except:

So you can see JavaScript scoping is actually extremely simple, albeit not always intuitive. A few things to be aware of:

  • var declarations are hoisted to the top of the scope. This means no matter where the var declaration happens, to the compiler it is as if the var itself happens at the top
  • multiple var declarations within the same scope are combined

So this code:

var i = 1;
function abc() {
  i = 2;
  var i = 3;
console.log(i);     // outputs 1

is equivalent to:

var i = 1;
function abc() {
  var i;     // var declaration moved to the top of the scope
  i = 2;
  i = 3;     // the assignment stays where it is

This may seem counter intuitive, but it makes sense from the perspective of a imperative language designer.

@Travis J 2015-09-14 20:29:53

The idea of scoping in JavaScript when originally designed by Brendan Eich came from the HyperCard scripting language HyperTalk.

In this language, the displays were done similar to a stack of index cards. There was a master card referred to as the background. It was transparent and can be seen as the bottom card. Any content on this base card was shared with cards placed on top of it. Each card placed on top had its own content which took precedence over the previous card, but still had access to the prior cards if desired.

This is exactly how the JavaScript scoping system is designed. It just has different names. The cards in JavaScript are known as Execution ContextsECMA. Each one of these contexts contains three main parts. A variable environment, a lexical environment, and a this binding. Going back to the cards reference, the lexical environment contains all of the content from prior cards lower in the stack. The current context is at the top of the stack and any content declared there will be stored in the variable environment. The variable environment will take precedence in the case of naming collisions.

The this binding will point to the containing object. Sometimes scopes or execution contexts change without the containing object changing, such as in a declared function where the containing object may be window or a constructor function.

These execution contexts are created any time control is transferred. Control is transferred when code begins to execute, and this is primarily done from function execution.

So that is the technical explanation. In practice, it is important to remember that in JavaScript

  • Scopes are technically "Execution Contexts"
  • Contexts form a stack of environments where variables are stored
  • The top of the stack takes precedence (the bottom being the global context)
  • Each function creates an execution context (but not always a new this binding)

Applying this to one of the previous examples (5. "Closure") on this page, it is possible to follow the stack of execution contexts. In this example there are three contexts in the stack. They are defined by the outer context, the context in the immediately invoked function called by var six, and the context in the returned function inside of var six's immediately invoked function.

i) The outer context. It has a variable environment of a = 1
ii) The IIFE context, it has a lexical environment of a = 1, but a variable environment of a = 6 which takes precedence in the stack
iii) The returned function context, it has a lexical environment of a = 6 and that is the value referenced in the alert when called.

enter image description here

@koredalin 2015-07-11 18:03:27

There are only function scopes in JS. Not block scopes! You can see what is hoisting too.

var global_variable = "global_variable";
var hoisting_variable = "global_hoist";

// Global variables printed
console.log("global_scope: - global_variable: " + global_variable);
console.log("global_scope: - hoisting_variable: " + hoisting_variable);

if (true) {
    // The variable block will be global, on true condition.
    var block = "block";
console.log("global_scope: - block: " + block);

function local_function() {
    var local_variable = "local_variable";
    console.log("local_scope: - local_variable: " + local_variable);
    console.log("local_scope: - global_variable: " + global_variable);
    console.log("local_scope: - block: " + block);
    // The hoisting_variable is undefined at the moment.
    console.log("local_scope: - hoisting_variable: " + hoisting_variable);

    var hoisting_variable = "local_hoist";
    // The hoisting_variable is now set as a local one.
    console.log("local_scope: - hoisting_variable: " + hoisting_variable);


// No variable in a separate function is visible into the global scope.
console.log("global_scope: - local_variable: " + local_variable);

@Bob 2017-03-22 16:13:55

(long time since answer posted ) Block scope ;…

@Yeasin Abedin Siam 2014-10-18 09:54:56

run the code. hope this will give an idea about scoping

Name = 'global data';
document.Name = 'current document data';
var Name = 'local data';
var myObj = {
    Name: 'object data',
    f: function(){

myObj.newFun = function(){

function testFun(){
    alert("Window Scope : " + window.Name + 
          "\nLocal Scope : " + Name + 
          "\nObject Scope : " + this.Name + 
          "\nCurrent document Scope : " + document.Name

@Anshul 2014-09-21 20:44:10

JavaScript have only two type of scope :

  1. Global Scope : Global is nothing but a window level scope.Here, variable present throughout the application.
  2. Functional Scope : Variable declared within a function with var keyword has functional scope.

Whenever a function is called, a variable scope object is created (and included in scope chain) which is followed by variables in JavaScript.

        a = "global";
         function outer(){ 
              b = "local";
              console.log(a+b); //"globallocal"

Scope chain -->

  1. Window level - a and outer function are at top level in scope chain.
  2. when outer function called a new variable scope object(and included in scope chain) added with variable b inside it.

Now when a variable a required it first searches for nearest variable scope and if variable is not there than it move's to next object of variable scope chain.which is in this case is window level.

@texasbruce 2015-02-28 21:50:07

Not sure why this is not the accepted answer. There is actually just functional scope (prior to ECMA6 there was no "local scope") and global bindings

@Gerard ONeill 2013-10-25 00:41:17

1) There is a global scope, a function scope, and the with and catch scopes. There is no 'block' level scope in general for variable's -- the with and the catch statements add names to their blocks.

2) Scopes are nested by functions all the way to the global scope.

3) Properties are resolved by going through the prototype chain. The with statement brings object property names into the lexical scope defined by the with block.

EDIT: ECMAAScript 6 (Harmony) is spec'ed to support let, and I know chrome allows a 'harmony' flag, so perhaps it does support it..

Let would be a support for block level scoping, but you have to use the keyword to make it happen.

EDIT: Based on Benjamin's pointing out of the with and catch statements in the comments, I've edited the post, and added more. Both the with and the catch statements introduce variables into their respective blocks, and that is a block scope. These variables are aliased to the properties of the objects passed into them.

 //chrome (v8)

 var a = { 'test1':'test1val' }
 test1   // error not defined
 with (a) { var test1 = 'replaced' }
 test1   // undefined
 a       // a.test1 = 'replaced'

EDIT: Clarifying example:

test1 is scoped to the with block, but is aliased to a.test1. 'Var test1' creates a new variable test1 in the upper lexical context (function, or global), unless it is a property of a -- which it is.

Yikes! Be careful using 'with' -- just like var is a noop if the variable is already defined in the function, it is also a noop with respect to names imported from the object! A little heads up on the name already being defined would make this much safer. I personally will never use with because of this.

@Benjamin Gruenbaum 2013-10-25 00:55:37

You have some mistakes here, for one JavaScript does have forms of block scoping.

@Gerard ONeill 2013-10-25 14:02:07

My ears (eyes) are open, Benjamin -- My statements above are how I've been treating Javascript scoping, but they are not based on reading the spec. And I hope you aren't referring to the with statement (which is a form of object scoping), or Mozilla's special 'let' syntax.

@Benjamin Gruenbaum 2013-10-25 16:42:18

Well, with statement is a form of block scoping but catch clauses are a much more common form (Fun fact, v8 implements catch with a with) - that's pretty much the only forms of block scoping in JavaScript itself (That is, function, global, try/catch , with and their derivatives), however host environments have different notions of scoping - for example inline events in the browser and NodeJS's vm module.

@Gerard ONeill 2013-10-25 19:00:40

Benjamin -- from what I can see, both with and catch only introduce the object into the current scope (and thus the properties), but then after the respective block ends, the variables are reset. But for example, a new variable introduced in a catch will have the scope of the enclosing function / method.

@Benjamin Gruenbaum 2013-10-25 19:01:06

Which is exactly what block scoping means :)

@Gerard ONeill 2013-10-25 19:04:01

I think at this point we'd enter into a semantic argument. But I'm glad to know about that little nuance anyway (even if it has never come up for me..)

@Gerard ONeill 2014-06-06 17:18:49

Massive edit on the post -- my misunderstanding was actually with how properties work. I also simplified what I was thinking about block scope to names defined just for the block.

@Jon Skeet 2009-02-01 08:31:34

Variables declared globally have a global scope. Variables declared within a function are scoped to that function, and shadow global variables of the same name.

(I'm sure there are many subtleties that real JavaScript programmers will be able to point out in other answers. In particular I came across this page about what exactly this means at any time. Hopefully this more introductory link is enough to get you started though.)

@Triptych 2009-02-01 08:33:47

I'm afraid to even begin answering this question. As a Real Javascript Programmer, I know how quickly the answer could get out of hand. Nice articles.

@Jon Skeet 2009-02-01 08:37:54

@Triptych: I know what you mean about things getting out of hand, but please add an answer anyway. I got the above just from doing a couple of searches... an answer written by someone with actual experience is bound to be better. Please correct any of my answer which is definitely wrong though!

@Triptych 2018-01-09 16:29:49

Somehow Jon Skeet is responsible for MY most popular answer on Stack Overflow.

@Mig82 2013-08-10 17:37:14

Try this curious example. In the example below if a were a numeric initialized at 0, you'd see 0 and then 1. Except a is an object and javascript will pass f1 a pointer of a rather than a copy of it. The result is that you get the same alert both times.

var a = new Date();
function f1(b)

@austincheney 2013-03-21 17:31:11

I found that many people new to JavaScript have trouble understanding that inheritance is available by default in the language and that function scope is the only scope, so far. I provided an extension to a beautifier I wrote at the end of last year called JSPretty. The feature colors function scope in the code and always associates a color to all variables declared in that scope. Closure is visually demonstrated when a variable with a color from one scope is used in a different scope.

Try the feature at:

See a demo at:

View the code at:

Currently the feature offers support for a depth of 16 nested functions, but currently does not color global variables.

@mplwork 2014-02-13 18:44:30

Doesn't work for me with Firefox 26. I paste code or load a file, click execute and nothing happens.

@Ben Aston 2020-02-27 17:53:11

Scope and inheritance are two difference things.

@krosenvold 2009-02-01 08:35:34

Javascript uses scope chains to establish the scope for a given function. There is typically one global scope, and each function defined has its own nested scope. Any function defined within another function has a local scope which is linked to the outer function. It's always the position in the source that defines the scope.

An element in the scope chain is basically a Map with a pointer to its parent scope.

When resolving a variable, javascript starts at the innermost scope and searches outwards.

@New Alexandria 2014-02-05 20:17:17

Scope chains are another term for [memory] Closures... for those reading here to learn / get into javascript.

@James McMahon 2012-05-15 17:38:30

The key, as I understand it, is that Javascript has function level scoping vs the more common C block scoping.

Here is a good article on the subject.

@kennytm 2010-04-06 11:19:39

In "Javascript 1.7" (Mozilla's extension to Javascript) one can also declare block-scope variables with let statement:

 var a = 4;
 let (a = 3) {
   alert(a); // 3
 alert(a);   // 4

@IgorGanapolsky 2010-12-28 17:39:14

Yeah, but is it safe to use? I mean would I realistically choose this implementation if my code will run in WebKit?

@kennytm 2010-12-28 18:29:11

@Python: No, WebKit doesn't support let.

@GazB 2012-10-11 08:06:17

I guess the only valid use for this would be if you knew all the clients would be using a Mozilla browser like for a companies internal system.

@Gerard ONeill 2013-10-25 00:02:20

Or if you are programming using the XUL framework, Mozilla's interface framework where you build using css, xml, and javascript.

@buzzsawddog 2013-11-22 17:49:42

@GazB even that is a horrid idea! So today you know that your clients are using Mozilla then out comes a new memo stating that now they are using something else. I.E. the reason our pay system sucks... You must use IE8 and never IE9 or IE10 or Firefox or Chrome because it flat out wont work...

@GazB 2013-11-25 09:04:46

@buzzsawddog I agree and hate systems that are limited to one browser but unforchantly it does happen and I was only saying that's at that time as far as I can see this was the only valid use for this. :)

@Oriol 2014-08-28 03:04:29

EcmaScript 6 draft introduces let, so other browsers will implement it. However, ES6 let behaves a bit different than mozilla's one.

@iAmOren 2020-07-01 07:15:32

The question was about var - true javascript. your answer refers to the pollution of js with "let". at least you didn't refer to the much worse "const". these are limitation borrowed for no reason from other languages and will never be used by me...

@geowa4 2009-02-01 08:48:09

Here's an example:


var globalVariable = 7; //==window.globalVariable

function aGlobal( param ) { //==window.aGlobal(); 
                            //param is only accessible in this function
  var scopedToFunction = {
    //can't be accessed outside of this function

    nested : 3 //accessible by: scopedToFunction.nested

  anotherGlobal = {
    //global because there's no `var`



You'll want to investigate closures, and how to use them to make private members.

Related Questions

Sponsored Content

95 Answered Questions

[SOLVED] How can I remove a specific item from an array?

  • 2011-04-23 22:17:18
  • Walker
  • 6845002 View
  • 8423 Score
  • 95 Answer
  • Tags:   javascript arrays

28 Answered Questions

[SOLVED] What does "use strict" do in JavaScript, and what is the reasoning behind it?

61 Answered Questions

[SOLVED] How do I include a JavaScript file in another JavaScript file?

37 Answered Questions

[SOLVED] What is the !! (not not) operator in JavaScript?

  • 2009-04-24 08:13:58
  • Hexagon Theory
  • 560605 View
  • 3150 Score
  • 37 Answer
  • Tags:   javascript operators

27 Answered Questions

86 Answered Questions

[SOLVED] How do JavaScript closures work?

23 Answered Questions

[SOLVED] What is the difference between call and apply?

3 Answered Questions

67 Answered Questions

[SOLVED] What is the most efficient way to deep clone an object in JavaScript?

4 Answered Questions

[SOLVED] Is there a reason for C#'s reuse of the variable in a foreach?

Sponsored Content