四时宝库

程序员的知识宝库

你不懂JS之作用域(js什么是作用域链)

作用域

大部分语言的最基础就是在变量中存储值,并且在稍后取出或修改这些值的能力。实际上,在变量中存储值和取出值的能力,给程序赋予了 状态

如果没有这样的概念,一个程序虽然可以执行一些任务,但是它们将会受到极大的限制。

但是在我们的程序中引入了变量,引出了我们现在将要解决的最有趣的问题:这些变量 存活 在哪里?换句话说,它们被存储在哪儿?而且,最重要的是,程序如何在需要它们的时候找到它们?

想要回答这些问题需要一组明确定义的概念规则,它定义如何在某些位置存储变量,以及如何在稍后找到这些变量。这组规则就是称为:作用域。

但是,作用域 的规则是在哪里、如何被定义的呢?

编译器理论

JavaScript 引擎在实施许多与传统的语言编译器相同的步骤,虽然是以一种我们不易察觉的更精巧的方式。

在传统的编译型语言处理中,一块儿源代码,你的程序,在它被执行 之前 通常将会经历三个步骤,

大致被称为“编译”:

  1. 分词/词法分析: 将一连串字符打断成(对于语言来说)有意义的片段,称为 token(记号)。

  2. 解析: 将一个 token 的流(数组)转换为一个嵌套元素的树,它综合地表示了程序的语法结构。这棵树称为“抽象语法树”(AST —— Abstract Syntax Tree)。

  3. 代码生成: 这个处理将抽象语法树转换为可执行的代码。这一部分将根据语言,它的目标平台等因素有很大的不同。

引擎如何管理系统资源的细节远比我们要挖掘的东西深刻,所以我们将理所当然地认为引擎有能力按其需要创建和存储变量。

和大多数其他语言的编译器一样,JavaScript 引擎要比这区区三步复杂太多了。例如,在解析和代码生成的处理中,一定会存在优化执行效率的步骤,包括压缩冗余元素,等等。

所以,我在此描绘的只是大框架。但是我想你很快就会明白为什么我们涵盖的这些细节是重要的,虽然是在很高的层次上。

其一,JavaScript 引擎没有(像其他语言的编译器那样)大把的时间去优化,因为 JavaScript 的编译和其他语言不同,不是提前发生在一个构建的步骤中。

对 JavaScript 来说,在许多情况下,编译发生在代码被执行前的仅仅几微妙之内(或更少!)。为了确保最快的性能,JS 引擎将使用所有的招数(比如 JIT,它可以懒编译甚至是热编译,等等),而这远超出了我们关于“作用域”的讨论。

为了简单起见,我们可以说,任何 JavaScript 代码段在它执行之前(通常是 刚好 在它执行之前!)都必须被编译。所以,JS 编译器将把程序 var a = 2;拿过来,并首先编译它,然后准备运行它,通常是立即的。

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言
    友情链接