变量与函数提升
- 变量声明提升
- 通过var定义(声明)的变量, 在定义语句之前就可以访问到
- 值: undefined
- 函数声明提升
- 通过function声明的函数, 在之前就可以直接调用
- 值: 函数定义(对象)
先有变量提升, 再有函数提升
/*变量提升*/console.log(a1) //可以访问, 但值是undefined/*函数提升*/a2() // 可以直接调用 输出a2()var a1 = 3function a2() {console.log('a2()')}
测试题
/*
面试题: 输出什么?
*/
var a = 4
function fn () {
console.log(a) //undefined 函数内部a变量提升
var a = 5
}
fn()
/*
测试题1: 先预处理变量, 后预处理函数
*/
function a() {}
var a;
console.log(typeof a)//function 变量提升后 函数提升覆盖了a
/*
测试题2: 变量预处理, in操作符
*/
console.log(b in window); //true {}无法生产作用域 b变量提升
if (!(b in window)) {//进不来b的赋值不执行 但变量提升了
var b = 1;
}
console.log(b) //undefined
/*
测试题3: 预处理, 顺序执行
*/
var c = 1
function c(c) {
console.log(c)
var c = 3
}
c(2) //c is no a function 解析如下
//function c 函数提升时已经执行 上边的代码可以理解为
//var c;
//function c...
//c=1
//c(2)
全局&函数执行上下文
- 理解
- 执行上下文: 由js引擎自动创建的对象, 包含对应作用域中的所有变量属性
- 执行上下文栈: 用来管理产生的多个执行上下文
- 分类:
- 全局: window
- 函数: 对程序员来说是透明的
- 生命周期
- 全局 : 准备执行全局代码前产生, 当页面刷新/关闭页面时死亡
- 函数 : 调用函数时产生, 函数执行完时死亡
包含哪些属性:
- 全局 :
- 用var定义的全局变量 ==>undefined
- 使用function声明的函数 ===>function
- this ===>window
- 函数
- 用var定义的局部变量 ==>undefined
- 使用function声明的函数 ===>function
- this ===> 调用函数的对象, 如果没有指定就是window
- 形参变量 ===>对应实参值
- arguments ===>实参列表的伪数组
```javascript
/*全局执行上下文**/
console.log(a1) //undefined console.log(a2) //undefined console.log(a3) //ƒ a3() {} // console.log(a4) //a4 is not defined console.log(this) //window
var a1 = 3 var a2 = function () { console.log(‘a2()’) } function a3() { console.log(‘a3()’) } a4 = 4
- 全局 :
/*函数执行上下文**/ function fn(x, y) { console.log(x, y) //1 2 console.log(b1) //undefined console.log(b2) //ƒ b2 () {} console.log(arguments) //Arguments(2) [1, 2] console.log(this)//window
console.log(b3) //b3 is not defined
var b1 = 5
function b2 () {
}
b3 = 6
} fn(1,2)
<a name="bstmy"></a>
# 执行上下文栈
1. 在全局代码执行前, JS引擎就会创建一个栈来存储管理所有的执行上下文对象
1. 在全局执行上下文(window)确定后, 将其添加到栈中(压栈)
1. 在函数执行上下文创建后, 将其添加到栈中(压栈)
1. 在当前函数执行完后,将栈顶的对象移除(出栈)
1. 当所有的代码执行完后, 栈中只剩下window
特点: **栈: 后进先出 **队列: 先进先出
> 图示代码在栈中执行过程

```javascript
//1. 进入全局执行上下文
var a = 10
var bar = function (x) {
var b = 5
foo(x + b) //3. 进入foo执行上下文
}
var foo = function (y) {
var c = 5
console.log(a + c + y)
}
bar(10) //2. 进入bar函数执行上下文
面试题
- 依次输出什么?
根据栈的特点后进先出,函数中递归导致压栈,所以会执行foo() begin先,而后foo() end再执行最后一个在栈最顶端最先执行
- global begin: undefined
- foo() begin: 1
- foo() begin: 2
- foo() begin: 3
- foo() end: 3
- foo() end: 2
- foo() end: 1
- global end: 1
- 整个过程中产生了几个执行上下文? 5个
console.log('global begin: '+ i) var i = 1 foo(1); function foo(i) { if (i == 4) { return; } console.log('foo() begin:' + i); foo(i + 1); //i是形参不是外部的i console.log('foo() end:' + i); } console.log('global end: ' + i)
