当JavaScript变量名称和函数名称相同时会发生什么?

时间:2016-11-18 11:20:23

标签: javascript function scope hoisting name-binding

我有以下代码,其中我声明了一个函数,然后是一个与函数同名的变量:

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

var a;
alert(a);

我希望这会提醒undefined,但如果我运行它,警报会显示以下内容:

  

功能a(x){
  返回x * 2
  }

如果我为变量指定了值(例如var a = 4),则警报会显示该值(4),但如果没有此更改,a将被识别为函数。

为什么会这样?

5 个答案:

答案 0 :(得分:12)

功能是一种对象,它是一种

值可以存储在变量(和属性中,并作为参数传递给函数等)。

功能声明:

  • 创建命名函数
  • 在当前作用域中创建一个与函数同名的变量(除非此类变量已存在)
  • 将该功能分配给该变量
  • 悬挂

var声明:

  • 使用指定的名称在当前作用域中创建变量(除非此类变量已存在)
  • 悬挂
  • 不为该变量赋值(除非与赋值运算符结合使用)

您的声明和var声明均已悬挂。只有其中一个为变量a赋值。

答案 1 :(得分:6)

在JavaScript中,函数声明变量声明都会被提升到函数的顶部,如果在函数中定义,或者在全局上下文的顶部,如果在外部一个功能。函数声明优先于变量声明(但不是变量赋值)。

功能声明会在提升时覆盖变量声明

首先声明一个变量:

var a; // value of a is undefined 

其次,a的值是一个函数,因为函数声明优先于变量声明(但不是变量赋值):

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

这就是你致电alert(a);时所得到的。

但是,如果不是声明变量而是进行变量赋值:var a = 4;,那么指定的值4将占上风。

答案 2 :(得分:2)

如果使用函数名作为变量名,则其值将替换为函数体。所以" var a"成为你的功能" a"身体,因此您的警报显示功能" a"。

答案 3 :(得分:2)

您还应该记住,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

答案 4 :(得分:0)

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