V8 blog 理解 ECMAScript 规范读后感

18次阅读

共计 1639 个字符,预计需要花费 5 分钟才能阅读完成。

本人的一个小读后感,读后感原文在博客链接,博客欢迎添加友链

https://blog.myim.online/blog/%E7%90%86%E8%A7%A3ecmascript%E8%A7%84%E8%8C%83/%E7%90%86%E8%A7%A3-ecmascript-%E8%A7%84%E8%8C%83%E8%AF%BB%E5%90%8E%E6%84%9F.html

ECMAScript 规范 链接 https://v8.dev/blog/tags/understanding-ecmascript

水平有限,欢迎指点批评

正文

ECMAScript 规范 这一合集,第一章主要讲了规范中的一些基础语法,注意,这里是规范的语法,

类似于!和?,问号比较常用,它的作用类似于解除包装后的值,这一语法挺像 rust 的 Some 去匹配 Option。

介绍完基本语法,第二章讲了非常实用的一个 js 操作,就是取值。

obj.foo 这个操作经历了什么,文章中是从底向上描述的。

如果是从顶向底描述,则是,obj.foo 这一个字符串先被词法分析器解析,解析之后,获得一个 Reference 对象,这个对象中包含了基值 obj 和键值 foo,之后就会传给GetValue

GetValue是一个规范内部的方法,接受一个参数 V,这个参数的类型是一个 Reference,Reference 中就包含了基值和键值,读这个方法,可以了解 js 的一些基本执行原理,下面是我自己对这个方法的描述;

如果 V 不是 Reference 类型,就直接返回 V,获取 Reference 中的 Base,即基值,然后判断基值是否为原始类型,就是 number,string 这些,如果是的话,就得把这些类型转为包装类型再调用其方法。如果不是原始类型,就调用 `[[Get]]` 方法,这个方法需要传入 V 的键值名字,还有一个 Receiver,Receiver 是通过 GetThisValue(V)获取的,这里的 GetThisValue,其实相当于获取 V 的 Base,基值。

[[Get]] 本身也是一个方法,

[[Get]](P,Receiver) 里面直接调用了?OrdinaryGet(O,P,Receiver),所以,直接看看 OrdinaryGet 的实现

OrdinaryGet 中详细定义了取值的规范。

下面我就把重要的过程描述一下:

取 obj 中的 foo 的值的时候,首先看对象本身有没有这个键值,如果没有,就调用 GetPrototypeOf 得到对象的原型,然后再调用原型的 `[[Get]](P,Receiver)`,这里就会产生递归,就会沿着原型链递归的查找键值。那如果对象本身有这个键值呢?那就直接返回就好了,这里要判断一下,是能直接取到值,还是被 getter 函数包装了,如果被 getter 函数包装了,就再调用一下 getter 函数,然后返回值。这里规范内部调用 getter 的时候,还需要传 Receiver

上面的过程,可以明显看出,整个调用过程的 Receiver 就没变过!

还可以注意到,Receiver 一直传,一直传,传到了哪里?有什么用?

用一个例子来解释下。

看下面的代码:

const o1 = {x: 10, get foo() {return this.x;} };
const o2 = {x: 50};
Object.setPrototypeOf(o2, o1);
o2.foo;
// → 50

调用 o2.foo 的时候,就找到了一个 o1 的 getter 函数,这里重要了,因为调用的是 getter,所以调用 getter 方法,

getter 方法传入的 Receiver 就是 o2,进入到函数中,再使用 this 时,这里的 this 就是指的 Receiver o2,因为上面所说,Receiver 就没变过。

所以,直接得出 o2.foo 的值就是 50,而不是 o1 中的 10。

从这个例子可以看出,规范中的一些定义,可以帮我们理清一些 js 怪异的行为,还是比较有帮助的。

怎么去阅读规范,那就是直接打开网页 https://tc39.es/ecma262/

正文完
 0