为什么需要函数提升?
这是为了解决两个循环调用的情况(函数A调用函数B,如果没有函数提升,就会始终有一个还没有声明,就会报错)
js函数提升是怎么做到的?
归功于执行上下文! 执行上下文又称执行环境(本文统一使用执行环境)
那么什么是执行环境?
执行环境定义了变量或者函数有权访问的其他数据,决定了他们各自的行为。每当JavaScript代码在运行的时候,它都是在执行环境中运行。
一个执行环境定义了函数执行时的环境。函数每次执行时对应的执行环境都是独一无二的,因此多次调用同一个函数会导致创建多个执行环境。当函数执行完毕,执行环境就被销毁。
执行环境的分类?
执行环境分为:
- 函数执行环境,
- 全局执行环境 ->是最外围的一个执行环境,在web浏览器中,全局执行环境是window对象。因此所有全局变量和函数都是作为window的属性和函数创建的。
- Eval 函数执行环境(最后一个不经常用,所以这里不讨论)
执行环境、变量对象(variable object)、活动对象(activation object)的关系?
- 每个执行环境都有一个与之关联的变量对象(VO)
- 变量对象(VO)保存的是这个环境中定义的所有的变量和函数。
- 当这个环境是函数时候,其活动对象(AO)就是变量对象。
- 一个函数的活动对象(AO)包含:局部变量、arguments、this。
执行环境的创建阶段?
当执行一个函数的时候,会首选创建该函数的执行环境,然后再一行一行执行。
创建执行环境: 也就是给执行环境创建一个作用域链——>这个作用域链的最前端,是当前执行代码所在环境的变量对象,当这个环境是函数时候,变量对象也就是活动对象。
这个作用域链的第二个变量对象,来自包含环境(外部一层),就这样依次顺延,直至延续要全局执行环境!
也就是说全局执行环境始终是作用域链中最后一个变量对象。
执行环境创建好后,就开始一行一行执行代码了,执行完之后,会将该执行环境出栈。
所以函数提升,或者变量提升,是因为在执行时候,已经创建好了执行环境(执行环境里面包含作用域链,因此作用域链也创建好了),只是在运行的时候,再进行赋值操作。 所以有函数提升,和变量提升:
console.log(a)
var a = 1
console.log(b)
function b(){
console.log('b')
}
打印结果:
// undefined
// ƒ b(){
console.log('b')
}