JavaScript—执行上下文和执行上下文栈
程序员文章站
2024-03-24 15:27:22
...
文章目录
1.变量提升与函数提升
1.变量声明提升:
*通过var定义(声明)的变量,在定义语句之前就可以访问到
*访问的值为:undefined;
2.函数声明提升:
*通过function声明的函数,在函数代码之前就可以直接调用
*访问的值为:函数定义
<script type="text/javascript">
var a=3;
function fn (){
console.log(a);
var a=4
}
fn();
//返回undefined
//原因:首先函数中有变量a,则不考虑全局的a=3;
//然后在函数中先定义a为undefined,再输入,最后再给a赋值为4
console.log(b); //返回undefined,可执行,变量提升;
fn2(); //可执行,函数提升;
fn3(); //不可执行,因为用的是关键字var,则为变量提升;
var b=3;
function fn2 (){
console.log('fn2()');
}
var fn3=function (){
console.log('fn3');
}
</script>
问题:变量提升和函数声明提升是如何产生的??
2.执行上下文
1.代码分类:
*全局代码
*函数(局部)代码
2.全局执行上下文:
在执行全局代码前,将window确定为全局执行上下文对象
对全局数据进行预处理:
1.var定义的全局变量——>undefined, 添加为window的属性;
2.function声明的全局函数——>定义,赋值(fun), 添加为window的方法;
3.this——>赋值(window)
开始执行全局代码;
3.函数执行上下文:
*在调用函数,准备执行函数体之前,创建对应的函数执行上下文对象
(函数执行上下文对象是一个虚拟的对象,作用类似全局中的window)
*对函数中的数据进行预处理:
1.形参变量——>赋值(实参) , 添加为执行上下文对象的属性;
2.arguments——>赋值(所有实参) , 添加为上下文对象的属性;
3.var定义的局部变量——>undefined , 添加为执行上下文对象的属性;
4.function声明的函数——>赋值(fun) , 添加为执行上下文对象的方法;
5.this ——>赋值(调用函数的对象)
*开始执行函数体代码;
a.变量提升与函数提升产生的原因:变量提升与函数提升就是执行上下文预处理的效果。
b.进行执行上下文预处理后,就按顺序进行执行;如果在执行有有函数,则再次进行函数的预处理。
c.执行上下文环境(对象)是动态的,调用函数时创建,函数调用结束时上下文环境(对象)就会被自动释放;(局部变量自动释放)
<script type="text/javascript">
//全局执行上下文
console.log(e); //undefined
console.log(window.e);
//预处理会将e添加为window的属性,所以e和window.e是一样的。
//this表示的是window;
var e=12;
function fun(){
console.log("fun()");
}
//函数执行上下文
function fn(a1){
console.log(a1); //2
console.log(a2); //undefined
a3(); //a3()
console.log(this); //window
console.log(arguments); //2,3 伪数组
var a2=3;
function a3(){
console.log('a3()');
}
}
fn(2,3);
//函数执行上下文对象,在调用函数时产生;
</script>
3.执行上下文栈
执行上下文栈:
1.在代码执行前,js引擎就会创建一个栈来存储管理所有的执行上下文对象;
2.在全局执行上下文window对象确定后,将其添加到栈中(压栈);
3.在函数执行上下文对象创建后,将其添加到栈中(压栈);
4.在当前函数执行完后,将栈顶的对象移除(出栈);
5.当所有的代码执行完后,栈中只剩下window;
<script type="text/javascript">
var a=10; //1.产生全局执行上下文window;
var bar =function (x){
var b=5;
foo(x+b); //3.产生foo函数的执行上下文对象;
}
var foo=function (y){
var c=5;
console.log(a+c+y);
}
bar(10); //2.产生bar函数的执行上下文对象;
</script>
栈结构:后产生的执行上下文对象,一定是先执行。
<script type="text/javascript">
console.log("gb:"+i);
var i=1;
foo(1); //产生执行上下文,
function foo(i){
if(i==4){
return
}
console.log("fb:"+i); //执行三次i=1,i=2,i=3
foo(i+1); //递归调用,在函数内部调用自己;
console.log("fe:"+i); //递归调用三次,执行三次i=3,i=2,i=1
}
console.log("ge:"+i);
</script>
1.依次输出什么?
gb:undefined
fb:1
fb:2
fb:3
fe:3
fe:2
fe: 1
ge: 1
2.整个过程中产生了几个执行上下文?
产生5次;1+1+3
var c=1;
function c(c){
console.log(c);
}
c(2); //结果为报错;
//原因:先变量c提升了,然后后执行c=1
//执行c=1后,此时c就是一个变量了,调用c(2)则会报错;
//函数还没调用,则函数里面的代码并未执行;
上一篇: hanoi汉诺塔问题的真谛
下一篇: [MyEclipse手册]代码自动补全
推荐阅读