变量提升与函数提升

201 阅读2分钟

一、变量提升

含义: js代码自上而下执行之前,浏览器会把所有带var/function关键字进行提前声明或定义。带var的关键字提前声明,function的关键字在变量提升阶段将定义和声明全部完成。

理解: js代码根据位置分为全局代码和局部代码。在执行全局代码前,会将window添加为全局执行上下文,进行如下预处理:

  1. 找到var关键声明的变量,赋值为undefined,且添加window属性。(变量提升)

  2. 将function声明的变量赋值fun(),添加为window属性。

  3. this (赋值window)

  4. 预处理结束,执行全局代码

//变量提升
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();

//局部变量的优先级高于同名的全局变量 。如果在函数中声明一个局部变量同名,则全局变量就会被局部变量覆盖。