变量提升和函数提升
通过var定义(声明)的变量,在定义语句之前就可以访问到。但是其值为undefined。
通过function声明的函数,在之前就可以直接调用
值:函数定义(对象)
var a=3
function fn(){
console.log(a)
var a=4
}
fn()
// 这里输出的是undefined,因为在定义语句之前就可访问。 变量提升
fn2()
function fn2(){
console.log('fn2()')
}
//在定义之前就可以调用 函数提升
fn3()
var fn3=function(){
console.log('fn3()')
}
//这里的fn3()并不能调用,因为这是变量提升
全局执行上下文
一.在执行全局代码前将window确定为全局执行上下文
二.对全局数据进行预处理
1.var定义的全局变量==>undefined,添加为window属性
2.function声明的全局函数==>赋值(fun),添加为window的方法
3.this==>赋值(window)
三.开始执行全局代码
函数执行上下文
一.在调用函数,准备执行函数体之前,创建对应的函数执行上下文对象(虚拟的,存在于栈中)
二.对局部数据进行预处理
1.形参变量==>赋值(实参)>添加为执行上下文的属性
2.arguments>赋值(实参列表),添加为执行上下文的属性
3.var定义的局部变量==>undefined,添加为执行上下文的属性
4.function声明的函数==>赋值,添加为执行上下文的方法
5.this==>调用函数的对象
三.开始执行函数体的代码
执行上下文栈
1.在全局代码执行前,js引擎会创建一个栈来存储管理所有的上下文对象
2.在全局执行上下文(window)确定后,将其添加到栈中(压栈)
3.在函数执行上下文创建后,将其添加到栈中(压栈)
4.在当前函数执行完后,将栈顶的对象移除(出栈)
5.当所有的代码执行完后,栈中只剩下window
补充
先执行变量提升,再执行函数提升。
function a(){}
var a
console.log(typeof a) //return 'function'
//因为先执行变量提升,后执行函数提升。所以a被定义为函数
var c=1
function c(c){
console.log(c)
var c=3
}
c(2) //报错
//因为函数提升和变量提升,所以在c赋值之前已经执行过function,
//在c(2)执行前c的实际值为c=1,所以此时c不是函数,会报错。我们可以等效为以下代码
var c
function c(c){
console.log(c)
var c=3
}
c=1
c(2)
Q.E.D.