美文网首页
作用域-javascript

作用域-javascript

作者: Mcq | 来源:发表于2019-06-26 12:39 被阅读0次

    1.编译理论

    传统的语言编译过程,会经过三步编译步骤(js的编译过程实际会复杂很多):
    1.标记/词法分析:

    var a = 2;会被分解为,var, a, =, 2, ;,空格可能会被标记。

    2.句法解析
    3.产生可执行的代码

    但是js并不会像其他语言有大量时间提前编译好。而是在代码执行的微妙级时间前编译,为了保证快速执行,js引擎用了各种各样的技巧。

    理解作用域

    理解作用域,我们可以想象一个对话过程。以var a = 2;为例。
    对话成员如下:

    • 引擎:负责全程编译和程序执行。
    • 编译器:引擎的一个朋友。句法解析,生成可执行代码。
    • 作用域:引擎的另一个朋友。搜集并维护一个向上查找的变量列表。强制执行一系列严格的规则,保证这些变量按规则被执行。

    当我们看到var a = 2;时,可能觉得这就是一个句子。而引擎看到的却是两个的语句,一个是编译器执行期间的语句,一个是引擎执行期间的语句。
    编译器对这个程序要做的第一件事是执行词法分析,将其分解为一个个标记,然后将其解析为词法树,但是,当编译器进入执行代码生成阶段时,它对待这个程序的方式可能与假定的有所不同。

    它会做如下事情:

    1.当遇到var a时,编译器会询问当前作用域集合是否已经存在一个变量a。如果存在,编译器将忽略此声明(var a)并继续执行。否则,编译器将要求当前作用域集合声明一个名为a的新变量。

    2.编译器然后生成可执行代码供引擎稍后执行,以处理a = 2语句。运行代码,引擎将首先询问作用域,在当前作用域集合中是否有一个名为a的变量。如果是,js引擎使用该变量。如果没有,js引擎将查找其他地方。

    如果最终找到了a变量,那么就会给它赋值为2.

    总结:变量赋值分为两步,首先,编译器声明一个变量(当前作用域没有声明变量的情况下),其次,当执行的时候,引擎会从当前作用域向上查找该变量并赋值.

    赋值操作的两个部分

    一,赋值的目标(变量)是谁?
    二,赋值的内容是什么?
    举个例子,

    console.log(a)属于第二部分,因为此时没有值赋值给a的操作.

    a = 2属于第一部分,不管此时a是什么值,现在给a赋值为2。

    另外一个例子,

    function foo(a) {
        console.log( a ); // 2
    }
    foo( 2 );
    

    函数调用阶段,属于赋值的第二部分,向上查找foo的值并调用它,(..)意味着foo的值应该是个函数,且需要马上执行。
    其中还包括了,当给函数传参时发生的a = 2这部分。

    执行console.log()log的时候,也属于第二部分,它会向上查找console有没有这个方法。

    作用域就是一系列的规则,以决定在哪里以什么样的方式查找变量。查找变量可能是为了给它赋值,也可能是为了获取变量的值。
    赋值操作,发生于使用赋值操作符= 或 给函数传参数的时候。

    js引擎在执行前会编译代码,编译分为两步,以var a = 2 ;为例:

    1.var a 在当前作用域顶部声明变量。
    2.a = 2,从当前作用域向上查找变量a,如果找到了就赋值。

    相关文章

      网友评论

          本文标题:作用域-javascript

          本文链接:https://www.haomeiwen.com/subject/rquuqctx.html