Что происходит, когда имя переменной JavaScript и имя функции одинаковы?

У меня есть следующий код, где я объявляю функцию и после нее переменную с тем же именем, что и функция:

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

var a;
alert(a);

Я ожидал, что это предупредит undefined, но если я запустил его, в сообщении появится следующее:

функция a (x) {     return x * 2
}

Если я присвою значение переменной (например, var a = 4), предупреждение отобразит это значение (4), но без этого изменения a будет распознано как функция.

Почему это происходит?

Ответ 1

Функции - это тип объекта, который является типом значения.

Значения могут храниться в переменных (и свойствах и передаваться как аргументы для функций и т.д.).

Объявление функции:

  • Создает именованную функцию
  • Создает переменную в текущей области с тем же именем, что и функция (если такая переменная уже не существует)
  • Назначает функцию этой переменной
  • Поднят

A var:

  • Создает переменную в текущей области с указанным именем (если такая переменная уже не существует)
  • Поднят
  • Не присваивает значение этой переменной (если в сочетании с оператором присваивания)

Подтверждаются как декларация, так и var. Только один из них присваивает значение переменной a.

Ответ 2

В JavaScript как объявление функции, так и объявление переменной выводятся наверх функции, если она определена в функции, или на вершину глобального контекста, если она находится вне функции. И объявление функции имеет приоритет над объявлениями переменных (но не над назначением переменных).

Объявление функции переопределяет объявление переменной при подъеме

Сначала вы объявляете переменную:

var a; // value of a is undefined 

Во-вторых, значение a является функцией, потому что объявление функции имеет приоритет над объявлениями переменных (но не над назначением переменных):

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

И это то, что вы получаете, когда вызываете alert(a); ,

Но, если вместо объявления переменной вы назначаете переменную: var a = 4; тогда присвоенное значение 4 будет преобладать.

Ответ 3

Если вы используете имя функции как имя переменной, ее значение заменяется на тело функции. Таким образом, "var a" становится вашей функцией "a", и, таким образом, ваше предупреждение отображает функцию "a".

Ответ 4

Вы также должны помнить, что var a поднят, что делает его более похожим на

var a; // placed

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

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

Помните, что var a поднят, поэтому, если вы назначили 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 предлагает лучшее решение, определив SyntaxError: Identifier (?) has already been declared при использовании let/const вместо 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

Обратите внимание, что const foo; не работает. Это вызовет SyntaxError: Missing initializer in const declaration