V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
royalknight
V2EX  ›  JavaScript

V8 blog 理解 ECMAScript 规范读后感

  •  
  •   royalknight · 64 天前 · 1132 次点击
    这是一个创建于 64 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

    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/

    2 条回复    2024-03-13 10:04:01 +08:00
    chnwillliu
        1
    chnwillliu  
       46 天前 via Android
    搭配 super 食用效果更佳,还有 super.xxx = 5 这种左值用法😂
    royalknight
        2
    royalknight  
    OP
       46 天前
    @chnwillliu 这一点还没看到
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5450 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 33ms · UTC 07:55 · PVG 15:55 · LAX 00:55 · JFK 03:55
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.