Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JavaScript 词法和类型 #64

Open
MengZhaoFly opened this issue Apr 18, 2020 · 0 comments
Open

JavaScript 词法和类型 #64

MengZhaoFly opened this issue Apr 18, 2020 · 0 comments

Comments

@MengZhaoFly
Copy link
Owner

MengZhaoFly commented Apr 18, 2020

类型

除了七种语言类型,还有一些语言的实现者更关心的规范类型。

  • List 和 Record: 用于描述函数传参过程。
  • Set:主要用于解释字符集等。
  • Completion Record:用于描述异常、跳出等语句执行过程。
  • Reference:用于描述对象属性访问、delete 等。
  • Property Descriptor:用于描述对象的属性。
  • Lexical Environment 和 Environment Record:用于描述变量和作用域。
  • Data Block:用于描述二进制数据

Completion Record

function foo(){
  try{
    return 0;
  } catch(err) {

  } finally {
    console.log("a")
  }
}

console.log(foo());

可以看到,finally 确实执行了,而且 return 语句也生效了,foo() 返回了结果 0。
虽然 return 执行了,但是函数并没有立即返回,又执行了 finally 里面的内容,这样的行为违背了很多人的直觉。
在 finally 中加入 return 语句,会发生什么?

function foo(){
  try{
    return 0;
  } catch(err) {

  } finally {
    return 1;
  }
}

console.log(foo());

finally 中的 return “覆盖”了 try 中的 return。
这一机制的基础正是 JavaScript 语句执行的完成状态,我们用一个标准类型来表示:Completion Record。

Completion Record 表示一个语句执行完之后的结果,它有三个字段:

  • [[type]] 表示完成的类型,有 break continue return throw 和 normal 几种类型;
  • [[value]] 表示语句的返回值,如果语句没有,则是 empty;
  • [[target]] 表示语句的目标,通常是一个 JavaScript 标签

语句几种分类:

image

普通语句

从前到后顺次执行(我们这里先忽略 var 和函数声明的预处理机制),没有任何分支或者重复执行逻辑。普通语句执行后,会得到 [[type]] 为 normal 的 Completion Record,JavaScript 引擎遇到这样的 Completion Record,会继续执行下一条语句。

语句块

语句块本身并不复杂,我们需要注意的是语句块内部的语句的 Completion Record 的[[type]] 如果不为 normal,会打断语句块后续的语句执行。

控制型语句

一类是对其内部造成影响,如 if、switch、while/for、try
另一类是对外部造成影响如 break、continue、return、throw
一般来说, for/while - break/continue 和 try - throw 这样比较符合逻辑的组合,是大家比较熟悉的,但是,实际上,我们需要控制语句跟 break 、continue 、return 、throw 四种类型与控制语句两两组合产生的效果。

image

穿透就是去上一层的作用域或者控制语句找可以消费break,continue的执行环境,消费就是在这一层就执行了这个break或者continue
try 和 finally 组合在一起:
finally 中的内容必须保证执行,所以 try/catch 执行完毕,即使得到的结果是非 normal 型的完成记录,也必须要执行 finally。而当 finally 执行也得到了非 normal 记录,则会使 finally 中的记录作为整个 try 结构的结果。

带标签的语句

JavaScript 语句是可以加标签的,在语句前加冒号即可:

out: while() {

}

跳出多层循环

let i = 0;
      out: while (true) {
        i++;
        console.log("out", i);
        inner: while (true) {
          if (i > 5) break out;
          i++;
          console.log("in", i);
        }
        if (i > 20) break;
      }

unicode

用 4 ~ 5 个16进制数字位表示每一个字符。
每个范围详细的表示:https://www.fileformat.info/info/unicode/block/index.htm
最常见的 0 ~ 128 范围表示的字符:https://www.fileformat.info/info/unicode/block/basic_latin/list.htm
常见的中文在 unicode 里面的表示:https://www.fileformat.info/info/unicode/block/cjk_unified_ideographs_extension_a/list.htm

'酷'.charCodeAt().toString(16)
= "9177"
'吧'.charCodeAt().toString(16)
"5427"
let \u9177\u5427 = 456
console.log(酷吧) // 456

词法: Lexical Grammar

js 接受 任意 unicode

词法分析

主要把 代码解析为以下部分
InputElementDiv ::

  • WhiteSpace
  • LineTerminator:换行
  • Comment
  • Token:任何有效的字符
vet ret = 0;
for (let i = 0; i < 10; i ++) {
 document.write(ret)
}

Token:

  • IdentifierName:标识符 i ret document write
    • keywords:关键字
    • Punctuator:符号 { } [ ] >=
  • Literal
    • NullLiteral
    • BooleanLiteral
    • NumericLiteral
    • StringLiteral
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant