浅谈js中的词法作用域、作用域和执行环境

最近温习了一下关于this的内容,发现以前看的知识点都忘了,所以为了不让自己再忘,就把自己当前的理解记录了下来。下面的理解如果存在不正确的地方欢迎大家指出哦。

1、定义

(1)词法作用域:是作用域的其中一个工作模型(另外一个是动态作用域,在js中只有this涉及动态作用域),词法作用域主要在代码的编译阶段,一个变量和函数的词法作用域取决于该变量和函数声明的地方。(而动态作用域是取决于变量和函数被调用的地方)。

(2)作用域:负责收集并维护由所有声明的标识符(变量)组成的一系列查询,并实施一套非常严格的规则,确定当前执行的代码对这些标识符的访问权限。

(3)执行环境:调用一个函数的时候都会创建一个执行环境,这个执行环境就是this的值,然而每个执行环境都有一个表示变量的对象叫做变量对象(依据arguments区别于活动对象,大多数情况下两者没什么特殊的区别,但由于全局对象没有arguments对象,所以不能叫做活动对象,只能叫做活动对象)。

2、区别

(1)词法作用域:我们知道,js是一种弱语言,实际上不存在编译阶段,只存在预编译和执行阶段,声明的变量和函数是在预编译阶段被解释的。例如var a=2;此时这条语句会被分为两部分,声明部分和定义部分,声明部分是在预编译阶段进行的,定义部分是在执行阶段执行的。编译器对声明的标识符进行了编译,并告知给相应的作用域(分为全局作用域和函数作用域,除了with和catch,其中with会修改词法作用域,catch会创建新的作用域,这两者看起来的效果很像块级作用域,但是es6的let声明的才是真正的块级作用域)。对了,还有,声明是可以提升的,就像下面这样,console.log(a);var a=2;这时,猜猜结果是什么呢,对了,就是undefined,因为上面的语句会被这样解析和执行 var a;console.log(a);a=2;但是如果变量是用let声明的就不会了哦,就会报ReferenceError。需要注意的是函数声明的提升是先于变量声明的提升的。一个语句的编译和执行是由作用域、编译器和引擎协同合作的。

var a=2;

function foo(){

console.log(a);

}

foo();

对a进行LHS(可以简单理解为赋值),这时引擎就会询问作用域是否有这么个东西声明过,如果有,就把2赋给它,如果这个作用域没有见过就会说没有,此时如果该作用域还不是全局作用域引擎就会往上询问,直到询问到全局作用域,如果还是没有见到a被声明过的影子就会在全局作用域创建个a,并把2赋给它。当执行foo()的时候就是对foo函数进行RHS查询(可以简单理解为取值),在foo()内部,遇到对a的RHS查询,在当前的函数作用域中找不到a,所以引擎就会往上一级的作用域询问,结果找到全局作用域就找到了a,就可以 把a的值在控制台打印了。

(2)作用域:平常我们讨论函数和变量的时候说的作用域的工作模型就是上面说的词法作用域了,但是this对象的作用域的工作模型是动态作用域,取决于函数在哪里被调用,所以this跟词法作用域半毛钱关系都没有,但是this有时会指向函数的作用域,有时指向函数本身(最常见的就是递归了)。下面这种情况说明上面的两种情况只是有时是正确的。

function foo(){

var b=1;

this.bar();

}

function bar(){

console.log(this.a)

};

foo();

这里的this就是执行环境都是全局对象(window,匿名函数的执行环境也是它哦),所以bar()里面的this.a其实就是window.a,但是我们并没有在全局声明定义过a啊,所以会报错啦。

(3)执行环境:this跟执行环境是息息相关的,每个执行环境都会有一个变量对象,全局环境的变量对象始终都存在。在执行环境中会维持一个作用域链(实际上就是一个指向变量对象的指针列表),在作用域链的开始就是一个指向全局的变量对象的指针,之后的就是该函数的调用函数的那些变量对象的指针啦,最后才是保存指向自己的变量对象的指针。但是哦,由于每个活动对象里面都有this和arguments对象(除了全局的变量对象没有arguments对象),所以我们每次查找this的时候只会查找当前的活动对象,并不会查找上级之类的活动对象中的this。

对于匿名函数,可以说是相当社会了,就是尽管包含匿名函数的函数执行完了,作用域链和执行环境要在内存中被回收了,但是内存不会动它的活动对象,因为这个活动对象现在还被匿名函数引用着,只要匿名函数没执行完,该活动对象就不会从内存中清除。

上面的那些仅仅是我个人对于作用域和this的浅淡的理解,或许会有不正确的地方,但是还是很想记录下来吐舌头

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值