当JavaScript变量名和函数名相同时会发生什么?
我有以下代码,其中我声明了一个函数,然后声明了一个与函数同名的变量:当JavaScript变量名和函数名相同时会发生什么?,javascript,function,scope,hoisting,name-binding,Javascript,Function,Scope,Hoisting,Name Binding,我有以下代码,其中我声明了一个函数,然后声明了一个与函数同名的变量: function a(x) { return x * 2; } var a; alert(a); 我希望此警报未定义,但如果我运行它,警报将显示以下内容: 函数a(x){ 返回x*2 } 如果我给变量赋值(如var a=4),警报将显示该值(4),但如果没有此更改,a将被识别为一个函数 为什么会发生这种情况?如果将函数名用作变量名,其值将替换为函数体。因此var a成为您的函数a,因此您的警报显示函数a 编辑但如果
function a(x) {
return x * 2;
}
var a;
alert(a);
我希望此警报未定义,但如果我运行它,警报将显示以下内容:
函数a(x){
返回x*2
}
如果我给变量赋值(如var a=4
),警报将显示该值(4
),但如果没有此更改,a
将被识别为一个函数
为什么会发生这种情况?如果将函数名
用作变量名
,其值将替换为函数体
。因此var a
成为您的函数a
,因此您的警报显示函数a
编辑但如果将值分配给a
如var a=“xya”代码>。然后它的函数
将被变量
替换。依照
变量赋值优先于函数声明
函数声明优先于变量声明
在JavaScript中,如果在函数中定义,则函数声明和变量声明都会提升到函数的顶部,如果在函数外部定义,则提升到全局上下文的顶部。函数声明优先于变量声明(但不优先于变量赋值)
提升时功能声明覆盖变量声明
首先声明一个变量:
var a; // value of a is undefined
其次,a
的值是一个函数,因为函数声明优先于变量声明(但不优先于变量赋值):
这就是你调用alert(a)时得到的结果代码>
但是,如果不声明变量,而是进行变量赋值:var a=4
然后以分配的值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分配给a
:
var a; // placed
function a(x) {
return x * 2;
};
var a = 4; // removed
a = 4 // added
alert (a); // a is now 4
函数是一种对象,它是一种值类型
值可以存储在变量(和属性)中,并作为参数传递给函数等
函数声明:
- 创建命名函数
- 在当前作用域中创建与函数同名的变量(除非该变量已存在)
- 将函数指定给该变量
- 吊运
Avar
语句:
- 在当前作用域中创建具有指定名称的变量(除非该变量已存在)
- 吊运
- 不为该变量赋值(除非与赋值运算符组合)
您的声明和var
声明均已挂起。其中只有一个为变量a赋值。ES6通过定义SyntaxError提供了一个更好的解决方案:当使用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
注意constfoo代码>不起作用。它将导致语法错误:const声明中缺少初始值设定项
您希望得到什么?变量和函数在JavaScript中共享相同的名称空间,因此它们相互重写。@Sirko我希望a是未定义的。如果函数名和变量名相同,那么JS引擎将忽略该变量。使用var a
创建一个新变量。声明实际上被提升到当前范围的开头(在函数定义之前)。之后,该名称将被相同名称的函数用完。这是使用alert()
时得到的结果。引擎首先提升变量(到未定义)。然后它提升函数声明。函数声明也被提升。Yes@Quentin但表达式不是或命名为表达式Yes@Quentin:函数声明和变量声明都被提升到包含范围的顶部。函数声明优先于变量声明(但不优先于变量赋值)。
function foo () {}
const foo = 1;
// => SyntaxError: Identifier 'foo' has already been declared