函数执行栈,在函数VO时入站,执行完AO时出栈ide
let a = 'Hello World!'; function first() { console.log('Inside first function'); second(); console.log('Again inside first function'); } function second() { console.log('Inside second function'); } first(); console.log('Inside Global Execution Context');
首先生命first入栈,以后生命second入栈,以后执行first可是first中执行了second,second执行完出栈,以后执行完first。函数
在执行上下文时,参数声明,函数声明,变量的声明。
参数声明》函数声明》变量声明若是变量对象已经包含了相同名字的属性,则替换它的值
this
function foo1(a){ console.log(a) function a(){} } foo1(20)//'function a(){}'
此时console.log(a),已经完成了VO阶段,也就上声明阶段,因为函数后声明,全部输出为函数。若是变量名和已经声明的函数名或者函数的参数名相同,则不会影响已经存在的属性
spa
function foo1(a){ console.log(a) function a(){} var a =1; } foo1(20)//'function a(){}'
函数的声明比变量优先级要高,而且定义过程不会被变量覆盖,除非是赋值指针
function foo(i){ var a = 'hello' var b = function(){} function c(){} } foo(22)
vo阶段code
ECObj = { scopChain: {...}, variableObject: { arguments: { 0: 22, length: 1 }, i: 22, c: pointer to function c() a: undefined, b: undefined }, this: { ... } }
ao阶段对象
ECObj = { scopeChain: { ... }, variableObject: { arguments: { 0: 22, length: 1 }, i: 22, c: pointer to function c() a: 'hello', b: pointer to function privateB() }, this: { ... } }
此时的console.log(typeof foo); console.log(typeof bar); 在函数的声明以后阶段(vo)blog
(function() { console.log(typeof foo); // 函数指针 console.log(typeof bar); // undefined var foo = 'hello', bar = function() { return 'world'; }; function foo() { return 'hello'; } }());
此时的console.log()为执行以后阶段(ao)作用域
(function() { var foo = 'hello', bar = function() { return 'world'; }; function foo() { return 'hello'; } console.log(typeof foo); // string console.log(typeof bar); // function }());