函数声明提升与变量声明提升

239 阅读3分钟

1.变量声明

if (true) {
    var a = "AAA";
}
console.log(a); //"AAA"

//预编译阶段
var a;
//执行阶段
if (true) {
    a = "AAA";
}
console.log(a); //"AAA"

var声明的变量存在Js全局作用域中,且在预编译阶段已经执行。

if (false) {
    var a = "AAA";
}
console.log(a); //"undefined"

//预编译阶段
var a;
//执行阶段
if (false) {
    a = "AAA";
}
console.log(a); //"undefined"

上述代码只声明了color变量却没有赋值,所以显示undefined。 JS编译器会把变量声明分为声明操作赋值操作。 声明操作在编译阶段进行,声明操作会被提升到执行环境的顶部,值是undefined(表示未初始化); 赋值操作会被留在原地等待执行阶段。注释:声明提前是在JavaScript引擎的预编译时进行,是在代码开始运行之前。

函数声明

创建函数第一种方法

函数声明会在编译阶段将函数和函数体提升到执行环境顶部,所以可以在函数声明前调用函数

sum(10, 10); //20
function sum(n1, n2) {
    return n1 + n2;
}

代码经过预编译阶段如下

var sum;
sum = function sum(n1, n2) {
    return n1 + n2;
}
sum(10, 10); //20

创建函数第二种方法(函数表达式)

var sum = function sum(n1, n2) {
    return n1 + n2;
}

通过匿名函数赋值给变量定义的方法叫做函数表达式,这种方式创建的函数没有函数声明提升

//经过预编译后代码如下
var sum;
sum = function sum(n1, n2) {
    return n1 + n2;
}

在函数表达式创建函数前创建函数前调用函数

sum(10, 10) //报错Uncaught TypeError: sum is not a function
var sum = function sum(n1, n2) {
    return n1 + n2;
}

因为通过函数表达式创建函数没有函数提升,调用时还没有创建函数,预编译后代码如下:

//预编译阶段
var sum;
//执行阶段
sum(10, 10);
sum = function sum(n1, n2) {
    return n1 + n2;
}

可以把函数表达式分为2步,第一步声明变量sum,第二步分给变量sum赋于这个匿名函数,而通过var声明的sum存在变量提升,在预编译阶段会提升到执行环境顶部,然后执行sum(10,10)就会报错,提示sum不是一个函数,undefined当然不是一个函数啦,执行完后,sum才指向了这个函数。

例题

第1题 同时存在函数声明和变量声明(函数声明优先)

getName();  //1
var getName = function () {
    console.log(2);
}

function getName() {
    console.log(1);
}

getName();  //2

预编译后:

var getName;
function getName() {
    console.log(1);
}
getName();  //1

var getName; //再次声明会被忽略
function getName() {
    console.log(2);
}
getName();  //2

第2题

var a = 1;
function b() {
    a = 10;
    return;

    function a() {
    }
}
b();
console.log(a);  //1

b函数内部存在函数变量声明提升,所以return后面的funtion a() {}会提升到当前执行环境顶部,因此b函数内部相当于声明了局部变量a,和全局作用域的a不同,当b执行完,局部变量被销毁。console.log(a)打印变量a的时候会搜索变量a,最后只在全局变量中发现了a。

//预编译后
var a = 1;
function b() {
    var a;
    function a() {}
    a = 10;
    return;
}
b();
console.log(a);  //1

参考:blog.csdn.net/weixin_3940…