What happens when JavaScript variable name and fun

2020-01-27 03:29发布

问题:

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?

回答1:

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.



回答2:

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.



回答3:

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



回答4:

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


回答5:

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