var的作用域提升
我们先来看下面的代码
for(; i < 10; i++) {
let i = 0;
console.log(i)
}
// Uncaught ReferenceError: i is not defined at <anonymous>:1:9
这意味着let 并不会有作用域的提升
接下来我们看下面的代码
var i = 0
for(;i < 10; i++) {
let i = 0;
console.log(i);
}
// 输出了 10 个 0
我们来分析一下这段代码,我们看到,开始的用 var 定义的 i,在循环体里面随着 i <10 做了十次自增。然后在子作用域里面又存在着一个自作用于里面的 i,循环了十次,输出了 10 次 let i = 0
紧接着,我们再看看下面的这段代码
for(; i < 10; i++) {
let i = 0;
console.log(i);
}
// Uncaught ReferenceError: i is not defined at <anonymous>:1:9
然后对比这个
for(; i < 10; i++) {
var i = 0;
console.log(i);
}
// undefined
再看看这个
for(let i = 0; i < 10; i++) {
let i = 0;
console.log(i);
}
// 输出了 10 个 0,只是说在这里面就拿不到 i 了
// 以上这个我们可以理解为 父作用域和子作用域,类似于:
{
let i =0;
{
let i = 1;
console.log(i);
)
console.log(i);
}
// 1 0
var 是有迷惑行为的(var 预处理机制)
for(i = 0; i < 10; i++) {
var i;
console.log(i);
}
// 等同于
var i;
for(i = 0; i < 10; i++) {
console.log(i);
}
//等同于
for(i = 0; i < 10; i++) {
console.log(i);
var i;
}
//甚至等同于
for(i = 0; i < 10; i++) {
console.log(i);
}
var i;
// Weird code
var x = 0
function foo() {
var o = { x: 1 }
x = 2
// var x = 2
// 'with' declared a seperate block
with (o) {
var x = 3
}
console.log(x)
}
foo()
console.log(x)
也就是说,不管 var 加在函数里面的什么地方,var 自动会变量提升到函数的最开始,对整个函数进行赋值操作,这是很迷惑的一个东西
所以,以后用 var,一定要在文件、函数的最开头声明
Brendan Eich:javascript-[with,var]这俩就是两个设计错误
winter:
-
如果非要用 var ,不建议大家写在任何的语句的子结构里面。有 var,我们一定要写在 function 的范围内,并且写在最前面,至少要写在第一次这个变量名出现的地方
function foo() { var o = {x: 1}; x = 2; if(false) { // 这句 var x = 1,也改变了 x = 2 的行为 var x = 1; } console.log(x); return // 这个 x = 3,照样改变了上面 x = 2 的行为 var x =3 } foo() console.log(x);
-
不要在任何的 block 里面写 var,其实在有的javascript编程规范里面建议完全舍弃 var,就用 let 还有 const,痛苦一点但是 resonable