通过函数声明与函数表达式理解函数执行上下文

1 js 函数定义的两种方法

1.1 函数声明

1
2
3
function sum(num1,num2){
return num1+num2;
}

1.2 函数表达式

1
2
3
var sum = function(num1,num2){
return num1+num2;
};

函数表达式方式末尾有一个分号,就像声明其他变量是一样。

2 函数声明与函数表达式的区别

解析器在向执行环境中加载数据时,对函数声明和函数表达式并非一视同仁。解析器会率先读取函数声明,并使其在执行任何代码前可用;至于函数表达式,则必须等到解析器执行到它所在的代码行,才会真正被解释执行。

1
2
3
4
5
6
7
8
9
10
console.log(sum(10,10));// 输出 20
function sum(num1,num2){
return num1+num2;
}

console.log(sum_e(10,10));// TypeError: sum_e is not a function
var sum_e = function(num1,num2){
return num1+num2;
}


函数声明和函数表达式的区别是JavaScript中函数执行上下文的规则导致的。那什么是函数执行上下文呢,有什么样的规则呢?

3 函数执行上下文

函数执行上下文(context)是JavaScript执行环境中的一种,是函数执行前进行的准备工作。

运行JavaScript代码时,当代码执行进入一个环境时,就会为该环境创建一个执行上下文,它会在你运行代码前做一些准备工作,如确定作用域,创建局部对象等。

4 执行上下文的生命周期

执行上下文的生命周期有两个阶段:

  1. 创建阶段(进入执行上下文)
  2. 执行阶段(代码执行

创建阶段:函数被调用时,进入函数环境,为其创建一个执行上下文,此时进入创建阶段。

执行阶段:执行函数中代码时,此时执行上下文进入执行阶段。

5 创建阶段的操作

  1. 创建变量对象
    • 函数环境会初始化创建Arguments 对象 (赋值
    • 函数声明 (赋值
    • 变量声明,函数表达式声明(未赋值
  2. 确定this指向(this由调用者确定)
  3. 确定作用域(词法环境决定,哪里声明定义,就在哪里确定)

6 执行阶段的操作

  1. 变量对象赋值
    • 变量赋值
    • 函数表达式赋值
  2. 调用函数
  3. 顺序执行其它代码

创建阶段对函数声明做赋值,变量及函数表达式仅做声明,真正的赋值操作要等到执行上下文代码执行阶段。