深刻理解JS的作用域链
admin
2023-08-02 15:52:38
0

作用域链的概念对理解闭包至关重要

先来一个例子

var scope = \"global\";
function CheckScope(){
    var scope = \"local\";
    return scope;
}
CheckScope();
//结果为local

1.当代码进入Global Execution Context后,会创建Global VO

2.当代码执行到CheckScope();语句的时候,进入CheckScope Execution Context;
根据上一篇文章<执行环境>的介绍,这里会创建CheckScope VO,
并设置CheckScope Execution Context的[[Scope]]属性

作用域链的创建规则

当定义一个函数时

在函数内部会创建一个[[Scope]]属性,这个属性指向一条作用域链。
也就是说在定义函数时,会事先创建一条作用域链。
这从chrome中可以看出来,如下图所示,即为我说的[[Scope]]属性

而这条事先就创建好的作用域链的创建规则也是很重要的,有以下几点:

  • JS中只有两种类型的作用域:全局作用域、函数作用域,所以在作用域链上的对象,只可能是window对象或者函数执行环境所对应的变量对象,但是with语句是一个例外,其可以临时在作用域链的前端临时增加一个普通对象
var o = {
    bruceZhou: \'bruceZhou\',
    fn: function(){
        console.log(fn)
        console.log(bruceZhou);
    }
}
o.fn();
//ERROR报错
//因为在执行匿名函数时,其作用域链为匿名函数所对应的变量对象--->window对象
//所以会找不到fn和bruceZhou的定义

//最重要的是其作用域链不包括对象o,对象o只负责保存fn
//在JS中只有全局作用域、函数作用域,并没有对象作用域这一说
//如果要在fn内部访问对象o,可以引用this或者使用with语句
  • 一个函数被定义时,在确定其[[Scope]]属性时,JS解释器执行如下的规则:从函数内部向外遍历,每当碰到一个function {...},就将其对应的变量对象添加至作用域链中去,如此下去,直到window对象,然后将作用域链的引用赋给[[Scope]]属性

当调用这个函数时

解释器会先创建一个新的变量对象,
然后将这个变量对象的添加至上面那个作用域链的栈顶,
此后将函数内部的[[Scope]]属性直接赋值给执行环境的[[Scope]]属性

当函数执行完之后

对应的函数执行环境会被销毁,
但该执行函数所对应的变量对象却不一定会被销毁,
这时就会发生闭包现象。

作用域链的数据结构

作用域即变量对象,作用域链是一个由变量对象组成的带头结点的单向链表,其主要作用就是用来进行变量查找。而[[Scope]]属性是一个指向这个链表头结点的指针。

带头结点的单链表

1.结点的存储结构(用C语言来表示)

typedef struct _tNODE{
    VariableObject *pVO;
    //指向一个变量对象,即指向一个作用域
    struct _tNODE *next;
    //指向下一个结点
}tNODE, *tPNODE;

2.猜想
我猜想作用域链的数据大概如下,是一个链栈,只是为了说明问题,不保证准确性,当然我也是不会为它负责的。

相关内容

热门资讯

500 行 Python 代码... 语法分析器描述了一个句子的语法结构,用来帮助其他的应用进行推理。自然语言引入了很多意外的歧义,以我们...
Mobi、epub格式电子书如... 在wps里全局设置里有一个文件关联,打开,勾选电子书文件选项就可以了。
定时清理删除C:\Progra... C:\Program Files (x86)下面很多scoped_dir开头的文件夹 写个批处理 定...
scoped_dir32_70... 一台虚拟机C盘总是莫名奇妙的空间用完,导致很多软件没法再运行。经过仔细检查发现是C:\Program...
65536是2的几次方 计算2... 65536是2的16次方:65536=2⁶ 65536是256的2次方:65536=256 6553...
小程序支付时提示:appid和... [Q]小程序支付时提示:appid和mch_id不匹配 [A]小程序和微信支付没有进行关联,访问“小...
pycparser 是一个用... `pycparser` 是一个用 Python 编写的 C 语言解析器。它可以用来解析 C 代码并构...
微信小程序使用slider实现... 众所周知哈,微信小程序里面的音频播放是没有进度条的,但最近有个项目呢,客户要求音频要有进度条控制,所...
Apache Doris 2.... 亲爱的社区小伙伴们,我们很高兴地向大家宣布,Apache Doris 2.0.0 版本已于...
python清除字符串里非数字... 本文实例讲述了python清除字符串里非数字字符的方法。分享给大家供大家参考。具体如下: impor...