执行上下文的生命周期
大体分为两个阶段
建立阶段
在这个阶段,执行上下文会分别建立变量对象,确认做用域链,以及肯定this的指向javascript
执行阶段
完成变量赋值,函数引用,以及执行其余代码java
变量对象(VO)
JavaScript代码中声明的全部变量都保存在变量对象中,除此以外,变量对象还可能包含如下内容函数
- 函数的说有参数(Firefox中为参数对象arguments)
- 当前上下文的全部函数声明(经过function声明的函数)
- 当前上下文中全部变量声明(经过var声明的变量)
变量对象的建立过程
- 函数的参数变量及其值
- 依次获取当前上下文中全部的函数声明,例如: foo:<foo reference>
- 依次获取当前上下文中的变量声明(经过var声明的变量),属性值会先被赋值为undefined,若是该变量名跟函数名同样,那么为了防止同名的函数被修改成undefined,则会跳过,原属性值不会被修改.(let/const是在执行上下文执行阶段开始执行的,避免了变量提高带来的影响)
实例分析
基于全局上下文分析this
//========= //demo1.js var a = 30 //第一步 var a = undefined //第二步 a = 30 //========= //=========start==== //demo2.js var a = 20 function fn(){console.log('fn')} function fn(){console.log('cover fn')} function a() {console.log('cover a')} console.log(a) fn() var fn = 'I want cover function named fn.' console.log(fn) //========= // 函数的声明优先级高于变量的声明 // 同名函数会覆盖函数与变量 // 同名变量不会覆盖函数 //建立阶段,声明 function fn(){console.log('fn')} function fn(){console.log('cover fn')} function a() {console.log('cover a')} var a = undefined var fn = undefined //建立阶段,按代码顺序进行赋值和函数的调用 a = 20 console.log(a) // 20 fn() //cover fn fn = 'I want cover function named fn.' console.log(fn) //'I want cover function named fn.' //=========end====
基于函数上下文分析spa
//demo1.js function test(){ console.log(a) console.log(foo()) var a = 1 function foo(){ return 2 } } test() //建立过程 testEC = { vo:{}//变量对象 scopeChain:[]//做用域链 this:{} } //就看该函数的执行上下文的VO的建立 Vo = { arguments:{...}, foo:<foo reference>, a:undefined } //执行阶段,活动对象AO,AO还包含了this的指向,全部你在函数中使用箭头函数的时候,this的指向也是经过这里肯定 VO=>AO = { arguments:{...}, foo:<foo reference>, a:undefined, this:window }
全局上下文的变量对象
每种语言总有一些普通奇奇怪怪的东西,例如:Java不支持多继承,恰恰默认继承Object对象code
windowEC = { vo:window, scopeChain:{}, this:window }