执行上下文
JavaScript属于解释型语言,javascript的执行分为:解释和执行两个阶段
解释阶段
- 词法分析
- 语法分析
- 作用域规则确定
执行阶段
- 创建执行上下文
- 执行函数代码
- 垃圾回收
变量或函数的上下文决定了他们可以访问哪些数据,以及它们的行为。每个上下文都有一个关联的变量对象而这个上下文中定义的所有变量和函数都存在于这个对象上。
全局上下文就是最外层的上下文。根据ECMAScript实现的宿主环境,表示全局上下文的对象可能不一样。在浏览器中就是window对象,因此所有通过var定义的全局变量和函数都会成为window对象的属性和方法。使用let和const的顶级声明不会定义在全局上下文中,但是作用域链解析的效果是一样的。上下文在其所有代码都执行完毕后会被撤销,包括定义在它上面的所有变量和函数(全局上下文在应用程序退出前才会被销毁,比如关闭网页或退出浏览器)。
每个函数调用都有自己的上下文。当代码执行流进入函数时,函数的上下文被推到一个上下文栈上。在函数执行完之后,上下文栈会弹出该函数上下文,将控制权返还给之前的执行上下文,ECMAScript程序的执行流就是通过这个上下文栈进行控制的。
上下文中的代码在执行的时候,会创建变量对象的一个作用域链(scope chain)。这个作用域链决定
了各级上下文中的代码在访问变量和函数时的顺序。代码正在执行的上下文的变量对象始终位于作用域
链的最前端。如果上下文是函数,则其活动对象(activation object)用作变量对象。活动对象最初只有
一个定义变量:arguments。(全局上下文中没有这个变量。)作用域链中的下一个变量对象来自包含上
下文,再下一个对象来自再下一个包含上下文。以此类推直至全局上下文;全局上下文的变量对象始终
是作用域链的最后一个变量对象。
内部上下文可以通过作用域链访问外部上下文中的一切,但外部上下文无法访问内部上下文中的任何东西。
上下文之间的连接是线性的、有序的。每个上下文都可以
到上一级上下文中去搜索变量和函数,但任何上下文都不能到下一级上下文中去搜索。
作用域
垃圾回收
标记清理
引用计数
闭包
闭包指的是那些引用了另一个函数作用域中变量的函数,通常是在嵌套函数中实现的。
练习
1、function aa(){
var a=10;
}
alert(a); //Error a is not defined
2、
var a=10;
function aaa(){
alert(a); //aaa被调用时,作用域链中的a为10
}
function bbb(){
var a=20;
aaa();
}
3、
var a=[1,2,3];
var b=[1,2,3];
function aaa(a,b){
a.push(4);
b=[1,2,3,4];
}
aaa(a,b);
alert(a); //[1,2,3,4]
alert(b); //[1,2,3]
4、var a=0;
console.log(a,window.a); //0,0
if(true) {
console.log(a,window.a) //f,0
a=10;
console.log(a,window.a) //10,0
function a(){}
console.log(a,window.a) //10,10
a=20;
console.log(a,window.a) //20,10
}
console.log(a,window.a) //10,10