欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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>

栈结构:后产生的执行上下文对象,一定是先执行。
JavaScript—执行上下文和执行上下文栈

<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)则会报错;
       //函数还没调用,则函数里面的代码并未执行;