javascript数据类型(六)--- 函数对象之执行上下文
一、引入
1.1 变量声明提升
通过var定义(声明)的变量, 在定义语句之前就可以访问到,其值为: undefined
var a = 3 function fn () { console.log(a) //输出结果为undefined var a = 4 } fn()
1.2 函数声明提升
通过function声明的函数, 在之前就可以直接调用,其值为: 函数定义(对象)
console.log(b) //undefined 变量提升 fn2() //可调用 函数提升 // fn3() //不能 变量提升 var b = 3 function fn2() { console.log('fn2()') } var fn3 = function () { console.log('fn3()') }
更多关于变量提升和函数提升的知识见https://www.cnblogs.com/echolun/p/7612142.html
二、执行上下文
执行上下文是一个比喻的词,用于描述运行Javascript代码的环境。JavaScript的代码按位置可简单分为全局代码和函数(局部)代码。在JavaScript中,每次运行一些Javascript代码时,引擎都会创造一个全局执行上下文,当调用函数时,在执行函数体之前,JavaScript引擎会创建一个局部的执行上下文。
2.1 全局执行上下文
执行全局代码的过程:
- 在执行全局代码前将window确定为全局执行上下文
- 对全局数据进行预处理
- var定义的全局变量==>undefined, 添加为window的属性
- function声明的全局函数==>赋值(fun), 添加为window的方法
- this==>赋值(window)
- 开始执行全局代码
2.2 函数执行上下文
执行局部(函数)代码的过程
- 在调用函数, 准备执行函数体之前, 创建对应的函数执行上下文对象(虚拟的, 存在于栈中)
- 对局部数据进行预处理
- 申明形参变量,并将实参变量的值赋值为形参变量,添加为执行上下文的属性
- arguments==>赋值(实参列表), 添加为执行上下文的属性
- var定义的局部变量==>undefined, 添加为执行上下文的属性
- function声明的函数 ==>赋值(fun), 添加为执行上下文的方法
- this==>赋值(调用函数的对象)
- 开始执行函数体代码
三、执行上下文栈
在全局代码执行前, JS引擎就会创建一个栈来存储管理所有的执行上下文对象(栈结构不了解的自行查询资料)。
- 在全局执行上下文(window)确定后, 将其添加到栈中(压栈)
- 在函数执行上下文创建后, 将其添加到栈中(压栈)
- 在当前函数执行完后,将栈顶的对象移除(出栈)
- 当所有的代码执行完后, 栈中只剩下window
如下代码执行的过程中会出现的上下文栈的变化图所示:
//创建全局上下文,并将该全局上下文储存到上下文栈中
var a = 10 var bar = function (x) { var b = 5 foo(x + b) //创建foo的局部上下文栈,并将该上下文对象存储到栈中,当函数foo执行完成后自动释放该执行上下文,跳到bar执行上下文中
}
var foo = function (y) {
var c = 5 console.log(a + c + y)
}
bar(10) //创建bar的局部上下文对象,并将该上下文对象存储到栈中
试题:
查看如此代码,分析输出内容
console.log('gb: '+ i) var i = 1 foo(1) function foo(i) { if (i == 4) { return } console.log('fb:' + i) foo(i + 1) //递归调用: 在函数内部调用自己 console.log('fe:' + i) } console.log('ge: ' + i)
答案:
gb: undefined fb: 1 fb: 2 fb: 3 fe: 3 fe: 2 fe: 1 ge: 1