你必须知道的javascript(上)- 1.作用域和闭包

Posted tangge

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了你必须知道的javascript(上)- 1.作用域和闭包相关的知识,希望对你有一定的参考价值。

1.1 编译原理

  • 分词/词法分析(Tokenizing/Lexing)
    将由字符组成的字符串分解成(对编程语言来说)有意义的代码块,这些代码块被称为词法单元(token)。
  • 解析/语法分析(Parsing)
    这个过程是将词法单元流(数组)转换成一个由元素逐级嵌套所组成的代表了程序语法结构的树。这个树被称为“抽象语法树”(Abstract Syntax Tree,AST)。
  • 代码生成
    将AST(抽象语法树)转换为可执行代码的过程称被称为代码生成

1.2 理解作用域

1.2.1 演员表

引擎(导演) 编译器(男主) 作用域(女主)

1.2.2 对话

1.遇到var a,编译器会问作用域是否已经有一个该名称的变量存在于同一个作用域的集合中。
2.接下来编译器会为引擎生成运行时所需的代码,这些代码被用来处理a = 2这个赋值操作。引擎运行时会首先询问作用域,在当前的作用域集合中是否存在一个叫作a的变量。如果是,引擎就会使用这个变量;如果否,引擎会继续查找该变量。

1.2.3 编译器有话说

当变量出现在赋值操作的左侧时进行LHS查询,出现在右侧时进行RHS查询。
考虑以下代码:
console.log( a );
其中对a的引用是一个RHS引用,因为这里a并没有赋予任何值。

LHS和RHS的含义是“赋值操作的左侧或右侧”并不一定意味着就是“=赋值操作符的左侧或右侧”。赋值操作还有其他几种形式,因此在概念上最好将其理解为“赋值操作的目标是谁(LHS)”以及“谁是赋值操作的源头(RHS)”。

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

最后一行foo(..)函数的调用需要对foo进行RHS引用,意味着“去找到foo的值,并把它给我”。并且(..)意味着foo的值需要被执行,因此它最好真的是一个函数类型的值!这里还有一个容易被忽略却非常重要的细节。

代码中隐式的a=2操作可能很容易被你忽略掉。这个操作发生在2被当作参数传递给foo(..)函数时,2会被分配给参数a。为了给参数a(隐式地)分配值,需要进行一次LHS查询。

这里还有对a进行的RHS引用,并且将得到的值传给了console.log(..)。console.log(..)本身也需要一个引用才能执行,因此会对console对象进行RHS查询,并且检查得到的值中是否有一个叫作log的方法。

最后,在概念上可以理解为在LHS和RHS之间通过对值2进行交互来将其传递进log(..)(通过变量a的RHS查询)。假设在log(..)函数的原生实现中它可以接受参数,在将2赋值给其中第一个(也许叫作arg1)参数之前,这个参数需要进行LHS引用查询。
技术图片

1.2.5 小测验

  1. 找到其中所有的LHS查询。(这里有3处!)
  2. 找到其中所有的RHS查询。(这里有4处!)
    技术图片

以上是关于你必须知道的javascript(上)- 1.作用域和闭包的主要内容,如果未能解决你的问题,请参考以下文章

读书笔记你不知道的JavaScript(上卷)--作用域是什么

《你不知道的JavaScript》 函数作用域和块级作用域

面向对象编程思想(前传)--你必须知道的javascript

面向对象编程思想(前传)--你必须知道的javascript(转载)

Javascript基础知识小测试

javascript 的作用域