var name = "why"
foo(123)
function foo(num) {
console.log(m)
var m = 10
var n = 20
}
函数执行过程:
1.在编译过程中:
发现foo是一个函数会自动在内存中再开辟一块空间
来存储foo函数(1.包含父级作用域即这个函数的上一层作用域也就是全局作用域(VO:GO)。2.包含函数的执行体(代码块))
因为是在内存中开辟的一块空间它就有一个对应这块空间的内存地址(因为是在内存种开辟的空间–一般的内存地址都是以0x开头的)
在GO中foo保存的是0x开头的这个地址,指向存储foo函数的内存
2.运行前:foo()
foo向GO中根据foo找到foo这块空间 然后()表示执行这时候会把这个内存中的函数放入到函数的调用栈(ECStack执行上下文栈)中进行调用,注意,这里不是将函数直接放到这个大的调用栈中执行,而是在原有的调用栈中再自动创建一个函数调用栈(函数执行上下文Function Execution Context简写SEC),这时候函数也不会直接执行在函数执行上下文中也会自动创建一个VO它对应的是AO,这个AO类似于GO是一个全局对象,AO对象会将函数中定义的变量提升到AO对象里,执行之前OA中的变量仍然是undefined
3.开始执行函数中代码:foo(123)
在AO对象中num被赋值为123,运行到console.log(m)时会先去AO中找,此时AO中的m是undefined,然后接着向下执行将m赋值为10,将n赋值为20
4.当函数中所有代码都执行完,当前函数的函数执行上下文就会弹出ECStack(调用栈)并且销毁掉,此函数执行上下文中的AO也会销毁掉
如果有执行了一次foo(321)会根据存放foo的内存空间再创建一个函数执行上下文,然后再放进ECStack调用栈执行以上步骤