LV2之-----JS 执行上下文环境(基石3)

23 篇文章 0 订阅
13 篇文章 0 订阅

执行上下文环境

一、学习目标
1.执行环境的基本概念
2.Js执行环境中准备了哪些东西?
3.执行流和执行环境栈
二、执行环境的概念
1.复习:栈的数据结构:先进后出、后进先出
类似于手枪的弹夹、杯子
在这里插入图片描述
2.EC:函数执行环境(或执行上下文),Execution Context
很多关于Context(上下文)的术语,如应用上下文,请求上下文等,查阅资料但没有得到理解?有没有比较好的解释?
每一段程序都有很多外部变量。只有像Add这种简单的函数才是没有外部变量的。一旦你的一段程序有了外部变量,这段程序就不完整,不能独立运行。你为了使他们运行,就要给所有的外部变量一个一个写一些值进去。这些值的集合就叫上下文。、
查不到是因为上下文这个东西不是一个具体的东西,上下文在不同的地方表示不同的含义,要感性理解。
context其实说白了,和文章的上下文是一个意思,在通俗一点,叫“环境”更好。
一篇文章,给你摘录一段,没前没后,你读不懂,因为有语境,就是语言环境存在,一段话说了什么,要通过上下文(文章的上下文)来推断。
子程序之于程序,进程之于操作系统,甚至app的一屏之于app,都是一个道理。
程序执行了部分到达子程序,子程序要获得结果,要用到程序之前的一些结果(包括但不限于外部变量值,外部对象等等);
app点击一个按钮进入一个新的界面,也要保存你是在哪个屏幕跳过来的等等信息,以便你点击返回的时候能正确跳回,如果不存肯定就无法正确跳回了。

3.ECS:执行环境栈,Execution Context Stack
4.变量对象VO(Variable object):
按照《JavaScript高级程序设计》的定义:执行环境定义了变量或者函数有权访问的其他数据,决定了他们各自的行为。每个执行环境都有一个与之关联的变量对象VO(Variable object)。环境中定义的所有变量和函数都保存在这个对象中。虽然我们在编写代码的时候无法访问这个对象,但解析器在处理数据时会在后台用到它。

5.AO激活对象(Activation object):
有了变量对象存每个上下文中的东西,但是它什么时候能被访问到呢?就是每进入一个执行上下文时,这个执行上下文儿中的变量对象就被激活,也就是该上下文中的函数标示符、形参、变量声明等就可以被访问到了。
其实变量对象和激活对象都是一个东西,只是变量对象是全局,激活对象是函数内部。
6.例:
对于晦涩难懂的概念,一般要借助实例来理解:
console.log(a);
//Uncaught ReferenceError: a is not defined

console.log(a);
var a;
//undefined

console.log(a);
var a =1;
//undefined

第一句会报错,因为我们试图打印一个未定义的变量;
第二句和第三句都输出了undefined,说明浏览器在打印的时候已经做了一些准备工作,知道a已经声明了,只是a还未被赋值。其实浏览器做的准备工作就发生在执行上下文环境中。我们可以这样来理解第三句代码:

var a;
	console.log(a);
	a = 10;

简单来说,就是将声明放到了当前作用域的顶部。
相同的情况还存在于函数的声明中。在前面的课程中,我们已经知道函数声明是有声明提升的,函数表达式不会存在这种情况。

console.log(fuc1);
function fuc1(){};
//fuc1
console.log(fuc2);
var fuc2 = function(){}
//undefined

上面演示的代码都是在全局环境中,在函数内部,我们还应该考虑arguments对象

function sayName(name){
		console.log(arguments)
	}
	sayName('xianyu')
        //["xianyu", callee: ƒ, Symbol(Symbol.iterator): ƒ]

我们并没有在函数内部定义arguments对象,但我们将它成功打印出来了,说明这个arguments对象也是在执行环境中准备好的。
除此之外,在js代码的任何位置打印this,它总是有值的,尽管大多数情况下this都指向window对象(this的具体指向以后会提到),这说明this也是在执行环境中就准备好的。
现在能清楚执行环境中准备了哪些东西了。
变量声明、函数声明、arguments(函数体)、this,以上内容都会被保存在变量对象中。由此可见,执行环境的作用就是生成一个变量对象,将代码执行过程中可能用到的所有变量都提前准备好。
三、执行流和执行环境栈
执行全局代码时,会产生一个执行上下文环境,每次调用函数都又会产生执行上下文环境。当函数调用完成时,这个上下文环境以及其中的数据都会被消除,再重新回到全局上下文环境。处于活动状态的执行上下文环境只有一个,这就是js的执行流机制。
Js执行流其实是一个压栈出栈的过程——执行上下文栈
在这里插入图片描述
1.JavaScript执行在单线程上,所有的代码都是排队执行
2.一开始浏览器执行全局的代码时,首先创建全局的执行上下文,压入执行栈的顶部。
3.每当进入一个函数的执行就会创建函数的执行上下文,并且把它压入执行栈的顶部。当前函数执行完成后,当前函数的执行上下文出栈,并等待垃圾回收。
4.浏览器的Js执行引擎总是访问栈顶的执行上下文。
5.全局上下文只有唯一的一个,它在浏览器关闭时出栈

在这里插入图片描述
6.例:借助一个案例进行理解:
//进入全局环境

1		var a = 10;
2		var fn;
3		var bar = function(x){//进入bar函数作用域
4			var b = 5;
5			fn(x+b);
6		}
7		fn = function(y){//进入fn函数作用域
8			var c = 5;
9			console.log(y+c)
10		}
11		bar(10)

在执行代码之前,首先将创建全局上下文环境。
在这里插入图片描述
然后是代码执行。代码执行到第11行之前,上下文环境中的变量都在执行过程中被赋值。
在这里插入图片描述
执行到第11行,调用bar函数。
跳转到bar函数内部,执行函数体语句之前,会创建一个新的执行上下文环境。
在这里插入图片描述
并将这个执行上下文环境压栈,设置为活动状态
在这里插入图片描述
执行到第5行,又调用了fn函数。进入fn函数,在执行函数体语句之前,会创建fn函数的执行上下文环境,并压栈,设置为活动状态。
在这里插入图片描述
待第5行执行完毕,即fn函数执行完毕后,此次调用fn所生成的上下文环境出栈,并且被销毁(已经用完了,就要及时销毁,释放内存)。
在这里插入图片描述
同理,待第11行执行完毕,即bar函数执行完毕后,调用bar函数所生成的上下文环境出栈,并且被销毁(已经用完了,就要及时销毁,释放内存)。
在这里插入图片描述
四、执行上下文的生命周期
总的的生命周期:创建→执行→出栈等待销毁
创建阶段:
创建作用域链(Scope Chain)
创建变量对象(或者AO):首先初始化函数的参数arguments,初始化函数声明,初始化变量(undefined)。函数的优先级要高于变量,如果变量和函数重名,变量会被忽略。
创建arguments对象,检查上下文,初始化参数名称和值并创建引用的复制。
扫描上下文的函数声明(而非函数表达式):
为发现的每一个函数,在变量对象上创建一个属性——确切的说是函数的名字——其有一个指向函数在内存中的引用。
如果函数的名字已经存在,引用指针将被重写。
扫描上下文的变量声明:
为发现的每个变量声明,在变量对象上创建一个属性——就是变量的名字,并且将变量的值初始化为undefined
如果变量的名字已经在变量对象里存在,将不会进行任何操作并继续扫描。
求出上下文内部“this”的值。
执行阶段:
执行变量赋值、代码执行
回收阶段:
执行上下文出栈等待虚拟机回收执行上下文
在这里插入图片描述
五、执行上下文的分析

<script>
var a1 = 19,
    a2 = 20,
    a3 = 'sss',
    b1 = { name: 'zhansan'};

a1 = f1(a1, a2);

function f1(a, b) {
  var t = 0,
      m = 10;
  for(var i = 0; i < a; i++) {
    console.log(i);
  }
  function f2() {
    console.log(f2);
  }
  return a + b;
}
</script>

在这里插入图片描述
六、JavaScript的解释和执行阶段
JavaScript的执行分为: 解释 和 执行两个阶段。
解释阶段:
词法分析
语法分析:看有没有报错。
作用域规则确定:判断一个变量是什么时,根据它定义时的作用域,代码在解释阶段就要确定好。
执行阶段:
创建执行上下文
执行函数代码
垃圾回收

JS代码运行前,有一个类似编译的过程即词法分析,词法分析主要有3个步骤:分析函数参数、分析变量声明、分析函数声明。
参考此处https://www.jianshu.com/p/d25b7a8a519f

一个极容易出错,又非常基础的JS面试题。

var v = 'global';function fn(){
    console.log(v);// global
    console.log(l);// undefined
    var l = 'local';
}
fn();

JS代码自上而下执行,但是JS代码整体运行分为两个阶段:词法分析期和运行期。在JS代码自上而下执行前,会有一个“词法分析过程”。

var v = 'global';function fn(){
    console.log(v);// global
    console.log(l);// Uncaught ReferenceError: l is not defined
    l = 'local';
}
fn();

(一)词法分析
JS代码运行前,有一个类似编译的过程即词法分析,词法分析主要有3个步骤:分析函数参数、分析变量声明、分析函数声明。

function fn(func){
    console.log(func);// func(){console.log(func);}
    function func(){
        console.log(func);// func(){console.log(func);}
    }
    func();
}
fn(1);

词法分析的具体步骤:在函数运行的瞬间,会生成一个活动对象(AO, Active Object)。
1.分析函数参数
将函数的形参添加为AO属性,属性的默认值为undefined。
接收函数的实参,并覆盖原属性值。
1.分析变量声明/分析局部变量
若AO中不存在与声明的变量所对应的属性,则添加AO属性为undefined。
若AO中已存在与声明的变量所对应的属性,则不做任何修改。
1.分析函数声明
若AO中存在与函数名所对应的属性,则覆盖原属性为一个函数表达式。

function fn(func){
    console.log(func);// func(){console.log(func);}
    var func = 100;
    function func(){
        console.log(func);// Uncaught TypeError: func is not a function
    }
    // func();
    console.log(func);// 100
}
fn(1);

具体分析如下
function fn(func){
console.log(func);
}/分析函数参数/// 将函数的形参添加为AO属性,属性的默认值为undefined。
fn();// undefined// 接收函数的实参,并覆盖原属性值。
fn(1);// 1
function fn(func){
console.log(func);// 1
/分析变量声明/分析局部变量/
// 若AO中已存在与声明的变量所对应的属性,则不做任何修改。
var func = 100;// 执行过程:对变量进行赋值
console.log(func);// 100
}
fn(1);

AO = {}
分析函数参数
AO = {func:undefined}
AO = {func:1}
分析局部变量
AO = {func:1}
运行阶段赋值
AO = {func:100}
function fn(func){
console.log(func);// func(){}
/分析变量声明/分析局部变量/
// 若AO中已存在与声明的变量所对应的属性,则不做任何修改。
var func = 100;// 执行过程:对变量进行赋值
console.log(func);// 100
/分析函数声明/
// 若AO中存在与函数名所对应的属性,则覆盖原属性为一个函数表达式。

 function func(){
    }
    console.log(func); // 100
}
f(1);

AO = {}
分析函数参数
AO = {func:undefined}
AO = {func:1}
分析局部变量
AO = {func:1}
运行阶段赋值
AO = {func:100}
分析函数声明
AO = {func:function(){}}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值