变量提升(hositing)
1. 变量提升
- 变量提升简单来说就是,先声明再赋值 先来用一个简单的栗子来说明
console.log(a); // undefined
var a = 0;
你没有看错,没有报错并且打印了undefined。
为什么在定义变量之前使用了变量还没有报错?这就是使用var声明的变量被提升到了代码的顶部,并且JS的代码执行是由上到下的,所以以上的代码可以被分解为:
var a;
console.log(a); // undefined
a = 0;
了解基本原理了吗?可以试着看一道面试题
var a=1;
(function(){
alert(a);
var a=2;
}())
是不是以为弹出了:1
弹窗执行结果是:undefined
这里有作用域的知识点,在js中,只有函数才会创建新的作用域,所以以上的代码可以分解为。
var a = 1; // 跟这个没关系了
// 此处构成了独自的作用域
(function(){
var a; // 优先自己作用域内的变量
alert(a); // undefined
a = 2;
}())
2. 函数提升
f();
function f() {
console.log('fff');
}
// 会正常打印 fff
其实和变量提升是一个道理,声明的函数会被直接提升到头部,上面的代码可以分解为:
function f() {
console.log('fff');
}
f();
那如果当var声明的变量和函数命名相同的时候会怎么样呢?看一个栗子:
console.log(a);
var a = 1;
function a() {}
console.log(a);
打印结果: f a() {} 和 1 ,虽然看起来有点绕,但是分解下代码就可以很清晰
var a; // 先出现先被提升到头部
function a() {}; // 覆盖变量a变为函数
console.log(a); // 此时a已经变成了 function a() {}
a = 1; // a 被重新赋值
console.log(a); // 1
变量提升也是有顺序的,按代码的执行顺序一个个提升到头部,就形成了上面的代码
2.2 函数表达式
函数表达式其实可以照做变量提升来看,并不会直接将函数提升到的顶部,相当于直接给变量赋值一个匿名函数。
// 可以这样实验一下
console.log(a);
var a = function() {}
// 拆解一下就是
var a;
console.log(a); // 打印了 undefined, 是不是与上面的变量提升一致
a = function(){}
经过上面的学习,最后用一到面试题校验自己的成果吧。
var global='global context';
var inner='global inner context';
function box(num){
console.log(global);
console.log(inner);
var inner='inner context';
console.log(inner);
num+=10;
return num;
}
var num=5;
var result=box(num);
console.log(result);
console.log(num);
来一起动手动脑分析和分解下:
var global='global context';
var inner='global inner context';
function box(num){
var inner;
console.log(global); //函数内部无global变量,向上级查找global变量
console.log(inner); //函数内部有inner变量,undefined
inner='inner context';
console.log(inner); // 局部变量inner被赋值,打印 inner context
num+=10; // 这里对函数的传参num进行计算,相当于被声明了局部变量,而不是全局变量num被重新赋值
return num;
}
var num=5;
var result=box(num); // 传入函数里的是num的副本而不是全局变量num本身,因此在函数里面修改参数值并不会对实参num造成影响
console.log(result); // 返回15;
console.log(num); // 依然是5