var a = 3
function fn(){
/*相当于先声明了a var a;a = undefined
先在自身函数中找变量,再去全局找
*/
console.log(a) //undefined
var a = 4
}
fn() //undefined
console.log(b) //undefined //变量提升
fn2() //可调用 函数提升
fn3() //变量提升,不可执行
var b = 3
function fn2(){
console.log(‘fn2‘)
}
var fn3 = function(){
console.log(‘fn3‘)
}
注意: 测试一:
function a(){}
var a
console.log(typeof a) //function
测试二:
var c = 1 //=>①var c
function c(c){
console.log(c)
var c = 3 //无关
}
//=>②c = 1 =>c typeof number
c(2) //报错c is not a function
代码分类(位置)
全局执行上下文
在执行全局代码前将window确定为全局执行上下文
对全局数据进行预处理(收集数据)
开始执行全局代码
c = 3 //特殊:未执行语句之前,window中不包含此变量,需用var定义
console.log(a1,window.a1) //undefined
a2() //a2()
console.log(this) //window
var a1 = 2
function a2(){
console.log(‘a2()‘)
}
console.log(a1) //2
函数执行上下文
在调用函数,准备执行函数体之前,创建对应的函数执行上下文对象(虚拟的,存在于栈中)
对局部数据进行预处理
开始执行函数体代码
function f1(a1){
console.log(a1)
console.log(a2)
a3()
console.log(this)
console.log(arguments)
var a2 = 3
function a3(){
console.log(‘a3()‘)
}
}
f1(2,3) //2,undefined,a3(),window,2 3
//调用一次函数产生一次执行上下文栈n+1(window)
//1、进入window全局执行上下文
var a = 10
var bar = function(x){
var b = 5
//2、进入foo执行上下文
foo(x + b)
}
var foo = function(y){
var c = 5
console.log(a + c + y)
}
//3、进入bar函数执行上下文
bar(10) //30


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)//递归调用:在函数内部调用自己
console.log(‘foo() end:‘ + i)
}
console.log(‘global end:‘ + i)
/*函数依次输出:
global begin:undefined
foo() begin:1
foo() begin:2
foo() begin:3
foo() end:3
foo() end:2
foo() end:1
global end:1
整个过程中产生了五个执行上下文
*/

原文:https://www.cnblogs.com/PHY01/p/15009407.html