不同情况下 var 定义变量作用域
内层外层函数的变量调用
- 在函数中,自己没有var 定义变量,只能去上一层找,更外部的就不行了
- 在函数中用var定义的变量是函数中的局部(私有)变量,从外界是无法访问的。
function out(){
var a = "out_";
function inner(){
a="inner_";
console.info(a);
}
console.info(a);
return inner;
}
var o = out(); //out_
o(); //inner_
out(); // out_
/*
1 第一次调用 out,把返回值 [ inner函数的地址 ] 给 o,但inner未被调用
2 调用 o,相当于直接调用内层的 inner,内层 inner 没有声明变量 a ,去父亲里找,把父亲的 a 改成inner_,输出
3 调用out,输出父亲的a,inner未被调用
*/
//inner中的 a 加了 var
function out(){
var a = "out_";
function inner(){
var a="inner_";
console.info(a);
}
console.info(a);
return inner;
}
var o = out(); //out_
o(); //inner_
out(); //out_
/*
1 第一次调用 out,把返回值 [ inner函数的地址 ] 给 o,但inner未被调用
2 调用 o,相当于直接调用内层的 inner,内层 inner 自己声明了变量 a,直接使用并输出
3 调用out,输出父亲的a,inner未被调用
*/
function out(){
var a = "out_";
function inner(){
a="inner_";
console.info(a);
}
inner(); //此处调用 inner
console.info(a);
return inner;
}
var o = out();
o();
/*
结果:
inner_ inner_
inner_
inner_ inner_
1 第一次调用 out,把返回值 [ inner函数的地址 ] 给 o,inner 在 out 内调用,inner 修改父亲的 a 后输出inner_ ; 弹出子函数,父亲的 a 已被儿子修改,输出修改后的 inner_
2 调用 o,相当于直接调用内层的 inner,自己没有定义 a ,在父亲中找到 a,修改并输出
3 调用out,inner 在 out 内调用,修改父亲的 a ,先输出;a 已被儿子修改,后输出
*/
function out(){
var a = "out_";
function inner(){
var a="inner_";
console.info(a);
}
inner();
console.info(a);
return inner;
}
var o = out();
o();
/*
结果:
inner_ out_
inner_
inner_ out_
1 第一次调用 out,把返回值 [ inner函数的地址 ] 给 o,inner 在 out 内调用,输出自己 a 的值 inner_; 弹出子函数,父亲的 a 未被修改仍为 out_
2 调用 o,相当于直接调用内层的 inner,输出自己的 a
3 调用out,inner 在 out 内调用,儿子的 a 是它自己的,父亲的 a 未被修改
*/
变量提升
- 在函数中用var定义的变量,声明会提升到函数作用域的顶端。
console.log(a); //undefined
var a = 'inner_';
console.log(a); //inner_
/*
定义后才能使用,否则为 undefined
*/
var a; //仅定义
console.log(a); //inner_
a = 'inner_';
console.log(a); //inner_
/*
js的预解析: js会优先去找在全局中用var声明的变量,将声明提升到全局作用域的顶端
*/
- 不带var定义的变量:必须是声明+赋值,变量的声明不会提升,否则会报错。
a = inner_;
console.log(a); //inner_
console.log(a); //如果把a写在下面,直接打印a会报错
a = inner_;
含参调用
函数中定义了形参a,如果在函数调用时不传参数,相当于在函数内部定义了a但是未赋值。
在函数调用时传实参,但写函数时没有写形参,实参时传不过去的。
var a = 3;
function fn(a) {
a = 'inner_';
console.log(a); //inner_
}
fn(0);
console.log(a); //3
/*
调用函数fn(0); 把实参0传递给形参a,此时相当于在函数内部声明a并赋值为0,
var a = 0,函数内部的a = 'inner_';会把a=0覆盖掉,所以内部打印的是inner_,
外部打印的还是外部的a,3
*/
var a = 3;
function fn() {
console.log(a);//3
a = 'inner_';
}
fn('out_');
console.log(a);//inner_
/*
1 调用函数fn('out_') 但因为函数中没有形参,实参 out_ 传不到函数中。函数中打印的a 依然是外部的a(3),
接着a = 'inner_'把函数外部的 a 覆盖
2 函数外部打印的 a 是覆盖后的 inner_
*/
var a = 3;
function fn(a) {
console.log(a);//3
a = 'inner_';
}
fn(a);
console.log(a);//3
/*
1 调用函数fn(a) 由于外部声明赋值了var a = 3,所以把实参 3 传给了函数的形参 a,相当于在函数内部声明并赋值了var a = 3,打印 a;
之后函数内部的 a = 'inner_' 把函数内部的 a 覆盖
2 在函数外部打印的 a 依然是外部的 a(3)
*/