var age = 23;
function foo() {
console.log(age);
var age = 65;
console.log(age);
}
foo();
输出:
undefined
65
但是
var a = 'hello!';
first();
function first() {
var b = 'hi!';
second();
function second() {
var c = 'hey!';
console.log(a + b + c);
}
}
输出:
hello!hi!hey!
为什么在第一个函数中age
是未定义的,而在第二个函数中,a
正确地绑定到hello!
?
因为当你使用var时,写这个:
function foo() {
console.log(age);
var age = 65;
console.log(age);
}
js认为你写了这个:
function foo() {
var age; // it is undefined
console.log(age);
age = 65;
console.log(age);
}
当您用var
声明变量时,局部变量的声明实际上发生在函数的顶部,它会从全局范围中隐藏变量。
同样正如评论中提到的,您应该真正使用let
或const
,而忘记var
。var
在这一点上已经过时了
在Javascript中,变量被"吊起",也就是说,即使您将age
放在foo
的第二行,实际上代码看起来像:
function foo() {
var age; // which in practice means that age = undefined
console.log(age);
age = 65;
console.log(age);
}
这是因为提升-使用var关键字创建变量的众所周知的问题。每次以这种方式声明时,无论在哪里声明,变量都会一直冒泡到函数的开头。这就是的原因
function foo() {
console.log(age);
var age = 65;
console.log(age);
}
类似于
var age = 23;
function foo() {
var age // age hoisted to here
console.log(age);
age = 65;
console.log(age);
}
这也造成了循环和异步操作的问题,如下所示:
function foo() {
for (var i = 0; i <= 6; i++) {
setTimeout(()=>console.log(i), 0)
}
}
foo()
您将得到7中的7,而不是像0,1,2..这样的预期输出,原因是相同的-var声明提升到函数的顶部,它分解了一个循环范围。然后循环结束其工作,i变为7,由于关闭,该值进入setTimeout回调。为了避免这种情况,根本不要使用var,因为ES6const和let都是最佳实践。