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

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

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

var a;
alert(a);

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

функция a(x) {
возвращает x * 2
}

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

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


person joesid    schedule 18.11.2016    source источник
comment
Что вы ожидаете? Переменные и функции используют одно и то же пространство имен в JavaScript, поэтому они переопределяют друг друга.   -  person Sirko    schedule 18.11.2016
comment
@Sirko Я бы ожидал, что a будет неопределенным   -  person joesid    schedule 18.11.2016
comment
если имя функции и имя переменной совпадают, то JS Engine игнорирует переменную.   -  person Sharath Bangera    schedule 18.11.2016
comment
С помощью var a вы создаете новую переменную. Объявление фактически поднимается до начала текущей области (перед определением функции). После этого имя используется одноименной функцией. Это то, что вы получаете при использовании alert().   -  person Sirko    schedule 18.11.2016
comment
Сначала движок поднимает переменные (в undefined). затем он поднимает объявления функций.   -  person OlehZiniak    schedule 18.11.2016


Ответы (5)


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

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

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

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

Утверждение var:

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

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

person Quentin    schedule 18.11.2016

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

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

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

var a; // value of a is undefined 

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

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

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

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

person Yosvel Quintero Arguelles    schedule 18.11.2016
comment
Объявления функций тоже поднимаются. - person Quentin; 18.11.2016
comment
Да @Quentin, но выражения не являются или именованными выражениями - person Akinjide; 18.11.2016
comment
Да @Quentin: объявление функции и объявления переменных поднимаются в верхнюю часть содержащейся области. И объявление функции имеет приоритет над объявлением переменной (но не над назначением переменной). - person Yosvel Quintero Arguelles; 18.11.2016

Если вы используете function name вместо variable name, его значение заменяется на function body. Таким образом, var a становится вашим function a, и, таким образом, ваше оповещение отображает функцию a.

Изменить Но если вы присвоите значение a, например var a = "xya";. Тогда function будет заменено на variable. В соответствии с порядком приоритета

  1. Присвоение переменной имеет приоритет над объявлением функции
  2. Объявления функций имеют приоритет над объявлениями переменных.
person Rahul Agrawal    schedule 18.11.2016

Вы также должны помнить, что 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
person Akinjide    schedule 18.11.2016

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

person themefield    schedule 10.07.2019