深入理解函数内部原理(2)——对一个函数实例进行深入的分析

时间:2022-12-08 19:09:25

——
在阅读本博客之前先阅读:
深入理解函数之函数定义、调用、解析、执行 解剖http://blog.csdn.net/wmaoshu/article/details/60469571
本博客是使用一个例子来对这个博客的进行说明

例子如下:

<script> "use strict"; var scope = "global scope"; var o = { "checkscope":(function g(){ var scope = "local scope"; console.log("o['checkscope']==this==>"+this); function f(){ console.log("f==this==>"+this); return scope; }; return f; }) }; console.log("return===>"+o["checkscope"]()()); /*结果为: o['checkscope']==this==>[object Object] f==this==>undefined return===>local scope */ </script>

进入全局代码
解析html代码到script标签开始调用script引擎解析js代码。在开始解析源代码之前,
进入全局代码执行环境,创建一个执行环境对象ExeGlobal,这个执行环境中此法环境和变量环境指向同一个词法环境LexGlobal,这个词法环境中的环境记录项是对象式环境记录项,与全局对象(window)绑定在一起,这个环境记录项的provideThis属性为false,外部词法环境为null。同时this与全局对象(window)绑定在一起。然后开始执行定义绑定初始化,将变量表达式scope、o作为window属性值为undefined添加到window中。
如下图所示:
深入理解函数内部原理(2)——对一个函数实例进行深入的分析
开始执行代码,执行到var scope = “global scope”;将window中scope属性值从undefined变为 “global scope”,然后执行对象o的定义,对对象中里面的属性开始解析,发现checkscope属性是一个函数,那么进行函数定义操作。

checkscope函数定义
Checkscope赋值函数是一个具名的函数表达式的形似,所以创建一个词法环境Lexcheckscope,这个词法环境中外部词法环境为该函数执行的所在的执行环境的词法环境,环境记录项Envcheckscope中会添加属性g,然后将调用创建函数对象的过程返回的结果赋值给g。
开始调用创建函数对象的过程:
传入参数函数体,参数列表,scope等,这里的scope为上一步创建的词法环境Lexcheckscope。
在这一步会创建一个对象checkscope,然后添加一些基础的属性比如[Class]、[prototype]等,特别的会有[Scope]属性,值为传入的scope,然后添加一些属性length为桉树参数的数目、constructor为会创建的函数checkscope、prototype为一个空的对象方便于继承,还有内部方法[Call][Construct][HasIntrace]等
深入理解函数内部原理(2)——对一个函数实例进行深入的分析
所以正式由于[scope]存在才会维护着作用域链,所以才会有闭包。

函数调用
开始执行o“checkscope”()。首先解析o[“checkscope”],返回一个引用Refcheckscope{base:o,name:checkscope,strict:true}.
然后根据这个引用通过getValue方式取得值为checkscope函数对象,经过检测之后这个值确实是一个函数对象,所以不会抛出TypeError错误异常。进一步开始确定this。
由于这个引用有效,则这个this就是基值o,开始通过[Call]方式以o作为this参数调用。
调用过程中,会为这个函数创建一个执行环境Execheckscope,这个执行环境中词法环境和变量化境会指向一个词法环境LEX,这个词法环境中环境记录项ENV为一个声明式环境记录项,外部词法环境为checkscope的[scope]属性的值。然后执行定义绑定初始化,在ENV中添加形参和实参的绑定、函数声明和函数对象的绑定、变量表达式与undefined的绑定。
深入理解函数内部原理(2)——对一个函数实例进行深入的分析
深入理解函数内部原理(2)——对一个函数实例进行深入的分析

执行完o“checkscope”后,接着返回的是一个函数f,从而执行o“checkscope”(),由于返回的是一个函数对象不是一个引用,所以这一this设置为undefined,然后开始通过[Call]调用f函数,创建执行环境Exef,由于处于严格模式下,所以执行环境Exef中this绑定为undefined。同时创建一个词法环境Envf,这个词法环境中环境记录项目也是通过定义初始化过程,同时外部词法环境为f的scope的值,也就是LEX,开始执行函数f。
深入理解函数内部原理(2)——对一个函数实例进行深入的分析
深入理解函数内部原理(2)——对一个函数实例进行深入的分析
深入理解函数内部原理(2)——对一个函数实例进行深入的分析

执行f之所以输出的是local scope,因为从Lexf中的Envf中查找内有scope,所以从LEX中的ENV中查找找到了就是这个scope的值。(蓝色线)