一、变量提升
含义: js代码自上而下执行之前,浏览器会把所有带var/function关键字进行提前声明或定义。带var的关键字提前声明,function的关键字在变量提升阶段将定义和声明全部完成。
理解: js代码根据位置分为全局代码和局部代码。在执行全局代码前,会将window添加为全局执行上下文,进行如下预处理:
-
找到var关键声明的变量,赋值为undefined,且添加window属性。(变量提升)
-
将function声明的变量赋值fun(),添加为window属性。
-
this (赋值window)
-
预处理结束,执行全局代码
//变量提升
console.log(a); //undefined
var a = 'hello';
console.log(a); //hello
其执行顺序等同于
var a;
console.log(a);
a='hello';
console.log(a);
二、函数提升
理解: 函数提升与变量提升原理相同,区别在于,函数提升已经创建好了函数对象,而变量提升赋值为undefined。 函数提升,只会提升函数声明,不会提升函数表达式。
var a = 1;
function foo() {
a = 10;
console.log(a);
return;
function a() {};
}
foo();
console.log(a);
//根据函数提升可将代码转换为:
var a = 1; // 定义一个全局变量 a
function foo() {
// 首先提升函数声明function a () {}到函数作用域顶端,
// 然后function a () {}等同于 var a = function() {};最终形式如下
var a = function () {}; // 定义局部变量 a 并赋值。
a = 10; // 修改局部变量 a 的值,并不会影响全局变量 a
console.log(a); // 打印局部变量 a 的值:10
return;
}
foo();
console.log(a); // 打印全局变量 a 的值:1
三、问题延伸
1.当函数同名会是什么情况
fn();//2
function fn() { console.log(1); }
fn();//2
var fn = 10;
fn();//报错 fn is not a function
function fn() { console.log(2); }
fn();
//函数同名,后声明函数会覆盖前面的函数
2.当变量同名时
//当全局变量和函数内部变量同名
var a = 1;
function test(x) {
alert(x);//undefined
alert(a);//undefined
var a = 2;
alert(a);//2
}
test();
//局部变量的优先级高于同名的全局变量 。如果在函数中声明一个局部变量同名,则全局变量就会被局部变量覆盖。