前言
在学习JavaScript时大家一定都知道,外部空间不能访问内部变量,我们往往只知道这一基本规则,那实现这一基本规则的基本底层原理是什么呢?今天我将从小白的角度来带大家理解作用域链,希望能给大家一些帮助!
作用域
1.什么是作用域
简单来说,作用域(英文:scope)是据名称来查找变量的一套规则,可以把作用域通俗理解为一个封闭的空间,这个空间是封闭的,不会对外部产生影响,外部空间不能访问内部空间,但是内部空间可以访问将其包裹在内的外部空间。
2.[[Scopes]]属性
在javascript中,每个函数都是一个对象,在对象中有些属性我们可以访问,有些我们是不能自由访问的,[[Scopes]]属性就是其中之一,这个属性只能被JavaScript引擎读取。
其实[[scope]]就是我们常说的作用域,其中存储了作用域运行期的上下文集合。
在这里因为func.prototype.constructor和func指向同一个函数,所以在这里我们通过访问函数func的原型对象来查看[[Scopes]]属性
3.作用域链
[[scope]]中存储的执行期的上下文对象的集合,这个集合呈链式连接,我们把这种链式连接叫做作用域链。JavaScript正是通过作用域链来查找变量的,其查找方式是沿着作用域链的顶端依次向下查询(在哪个函数内部查找对象,就在哪个函数作用域链中查找)
4.图解查找变量原理
//以如下代码为例说明JavaScript通过作用域链查找变量的原理**
function a() {
function b() {
//这里原来我给的b的值是234,后面经过评论区提醒后面的图写的是123,所以我将b的值改为了123
var b = 123;
}
var a = 123;
b();
}
var glob = 100;
1.当全局函数a()被定义时,作用域链如下
函数的[[Scopes]]属性指向作用域链对象,此时作用域链只有一个键值对,这个键值对指向全局对象,全局对象存储了全局下可以访问的东西,也就是最外层作用域,大家都可以访问的。
2.当全局函数a()被激活调用时,作用域链如下
此时作用域链能够第一个访问的是Activation Object中的键值对,如果没有才访问全局对象
3.函数a()中函数b被定义时,b的作用域链如下
当b只是被定义没有被调用时,b的作用域链和a是相同的
4.当函数a()中的函数b被激活调用时,作用域链如下
作用域链最先指向函数b()的Activation Object,查找变量也是按作用域链顺序访问,找到就停止
总结
之所以外部作用域不能访问内部作用域的原因是外部作用域的作用域链没有内部作用域的Activation Object,所以无法访问内部变量,内部作用域访问变量的顺序是按照作用域链,先从里面查找,没有就沿着作用域链向外找,外部是全局作用域。
到此这篇关于JavaScript作用域链底层原理的文章就介绍到这了,更多相关JavaScript作用域链内容请搜索极客世界以前的文章或继续浏览下面的相关文章希望大家以后多多支持极客世界! |
请发表评论