js中的预编译和作用域链

预编译目的

1. 定义作用域中的初始化词法环境,而词法环境中有定于作用域,从而规定了变量的作用域

2. 先是在为undefined,减少运行时报错

形参去实参的区别

1.形参变量只有在被调用时才分配内存单元,在调用结束时, 即刻释放所分配的内存单元。因此,形参只有在函数内部有效。 函数调用结束返回主调函数后则不能再使用该形参变量。

2.实参可以是常量、变量、表达式、函数等, 无论实参是何种类型的量,在进行函数调用时,它们都必须具有确定的值, 以便把这些值传送给形参。 因此应预先用赋值,输入等办法使实参获得确定值。

function add(a,b) {
    return a + b
};
add(1,2);
// a,b是形参,1.2是实参

JavaScript运行三部曲

脚本执行js引擎都做了什么呢?

  1. 语法分析
  2. 预编译
  3. 解释执行

1.语法分析:分析语法是不是错了

2在语句执行的时候会先进行预编译

3.在编译完了进行语句执行

下面就是编译的主要步骤

预编译的过程(分四步):

1.(对函数)创建AO对象;(对全局的时候也就是Window)创建GO对象

2.找形参和变量声明,将变量名和形参名作为(AO对象,或GO对象)的属性值 初始值为undefined

3.将实参值传递形参统一

4.在函数体里面找函数声明,值赋予函数体

A0,GO就是执行期的上下文定义了一个函数的执行环境(词汇环境),当一个函数在执行的前一刻,会创建一个执行期上下文(执行上下文创建的时间),并且每次在函数执行的时候这个执行期上下文都是不相同的,因为没一次都是全新的

在预编译和执行的过程会对赋值语句会对AO,GO中的变量进行覆盖,应该以执行结束后的结果为最终的变量标准。

当出现同命的时候函数为什么会覆盖变量应为函数是第4步变量是第二步就复制了,所以会函数的优先级高

下面是一个例子的全过程:

    <script type="text/javascript">
		global = 100;
		function fn(){
			console.log(global); //undefined
			global = 200;
			console.log(global); //200
			var global = 300;
		}
		fn();
		var global;
	</script>

 第一阶段全局预编译

1.首先全局对象创建GO执行上下文
GO{
    2.对形参和变量声明,将其作为属性名,值为undefined
    global:undefined
    3.全局对象没有形参
    4.在函数体里找函数声明,值赋予函数体
    fn:function fn(){};
}

第二阶段执行代码

1. global = 100
2.fn();(先预编译fn(),在执行)

第三阶段 :由于fn函数要执行了先对其进行预编译

1. 对函数产生AO环境
AO{
 2.对形参和变量声明,将其作为属性名,值为undefined
    //当局部变量AO中存在的时候先找局部变量AO里的变量,这个时候虽然GO全局中存在global为100,但局部中已经有global为undefined
    global:undefined --fn的AO执行到第二句-->200 --fn的AO执行到第四句-->300
 3.没形参
 4.没函数声明
}

第四步:执行fn() 

A0执行{
    第一句:console.log(global); //undefined在AO的执行上线中global:undefined;
    第二句:global = 200;
    第三句:console.log(global); //在AO中找global已经变成了200
    第四句:global = 300; //
}

最终结果 

    GO{
      global:100
      fn:function fn(){ };
    }
    AO{
      global:300
    }

只有把这个看懂了(看懂一点也没关系)下面我们来写什么是作用域链 ,看完了什么是

作用域链

函数也是一个对象在这个对象中有些我们可以访问的属性比如prototype,name,不可以访问的有[[scope]]属性

[[scope]]属性:指的就是我们所说的作用域,其中储存了运行期上下文(执行期上线下文A0 G0)的集合

作用域链:[[scope]]中储存的执行期上下文对象的集合,这个集合呈链式链接,也叫作用域链

下面看一个例子

function a() {
  function b() {
    var b = 234;
  }
  var a = 123;
  b();
}
var glob = 100;
a();

图一:在b定义的时候a马上快执行完的时候的图像

图二:在b自己执行的时候会变成

    

当b执行的时候:首先b会继承了aAO和GO,这里的aAO全等于a中的aAO

scope chain(栈的形式:先进后出)中的数值代表数值的key,key代表:

  • 0 ---自己的AO(Activation Object)
  • 1---a的AO
  • 2---GO(Clobal Object)

由于由作用链的关心才可以说(0--自己OA中没有的变量)可以向上(1---a中的OA)找或者(2---GO)中找,也为以后闭包产生做铺垫

子 - 父 -祖宗--全局 这样一个(作用域链)的过程

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值