25

I have the following code, where I declare a function and after it, a variable with the same name as the function:

function a(x) {
    return x * 2;
}

var a;
alert(a);

I expected this to alert undefined, but if I run it, the alert will display the following:

function a(x) {
    return x * 2
}

If I assign a value to the variable (like var a = 4), the alert will display that value (4), but without this change a will be recognized as a function.

Why is this happening?

totymedli
  • 23,114
  • 18
  • 109
  • 143
joesid
  • 583
  • 1
  • 8
  • 20
  • 2
    What is it you would expect? Variables and functions share the same namespace in JavaScript, so they override each other. – Sirko Nov 18 '16 at 11:21
  • @Sirko I would expect a to be undefined – joesid Nov 18 '16 at 11:22
  • if function name and variable name are same then JS Engine ignores the variable. – Sharath Bangera Nov 18 '16 at 11:23
  • 1
    With `var a` you create a new variable. The declaration is actually hoisted to the start of the current scope (before the function definition). Afterwards the name is used up by the function of the same name. This is what you get when using `alert()`. – Sirko Nov 18 '16 at 11:23
  • 1
    The engine first hoists variables (to undefined). then it hoists function declarations. – OlehZiniak Nov 18 '16 at 11:23

5 Answers5

23

Functions are a type of object which are a type of value.

Values can be stored in variables (and properties, and passed as arguments to functions, etc).

A function declaration:

  • Creates a named function
  • Creates a variable in the current scope with the same name as the function (unless such a variable already exists)
  • Assigns the function to that variable
  • Is hoisted

A var statement:

  • Creates a variable in the current scope with the specified name (unless such a variable already exists)
  • Is hoisted
  • Doesn't assign a value to that variable (unless combined with an assignment operator)

Both your declaration and var statement are hoisted. Only one of them assigns a value to the variable a.

Quentin
  • 800,325
  • 104
  • 1,079
  • 1,205
9

In JavaScript both function declaration and variable declarations are hoisted to the top of the function, if defined in a function, or the top of the global context, if outside a function. And function declaration takes precedence over variable declarations (but not over variable assignment).

Function Declaration Overrides Variable Declaration When Hoisted

First you declare a variable:

var a; // value of a is undefined 

Second, the value of a is a function because function declaration takes precedence over variable declarations (but not over variable assignment):

function a(x) {
  return x * 2;
}

And that is what you get when you call alert(a);.

But, if instead of declaring a variable you make variable assignment: var a = 4; then the assigned value 4 will prevail.

Nicholas K
  • 14,118
  • 7
  • 25
  • 49
Yosvel Quintero Arguelles
  • 15,149
  • 4
  • 33
  • 35
4

If you use a function name as variable name, its value is replaced by function body. So var a becomes your function a and thus your alert displays function a.

Edit But if you assign value to a like var a = "xya";. Then it function will be replaced by variable. As per Order of precedence

  1. Variable assignment takes precedence over function declaration
  2. Function declarations take precedence over variable declarations
Karan
  • 10,338
  • 3
  • 20
  • 35
Rahul Agrawal
  • 519
  • 1
  • 3
  • 17
2

You should also remember that var a is hoisted, which makes it more like this

var a; // placed

function a(x) {
  return x * 2;
};

var a; // removed
alert (a); // a is replaced by function body

Remember that var a is hoisted, so if you assign 4 to a:

var a; // placed

function a(x) {
  return x * 2;
};

var a = 4; // removed
a = 4 // added

alert (a); // a is now 4
Akinjide
  • 2,575
  • 19
  • 27
-1

ES6 comes with a better solution by defining SyntaxError: Identifier (?) has already been declared when using let / const instead of var.

let

function foo () {}
let foo;
// => SyntaxError: Identifier 'foo' has already been declared

const

function foo () {}
const foo = 1;
// => SyntaxError: Identifier 'foo' has already been declared

Note that const foo; does not work. It will cause SyntaxError: Missing initializer in const declaration

themefield
  • 2,454
  • 25
  • 28