V8 blog 理解 ECMAScript 规范读后感 - V2EX
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 2024-02-24 13:53:34 +08:00 1896 次点击
    这是一个创建于 594 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

    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  
       2024-03-12 18:57:53 +08:00 via Android
    搭配 super 食用效果更佳,还有 super.xxx = 5 这种左值用法
    royalknight
        2
    royalknight  
    OP
       2024-03-13 10:04:01 +08:00
    @chnwillliu 这一点还没看到
    关于     帮助文档 &nbp;   自助推广系统     博客     API     FAQ     Solana     891 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 20:55 PVG 04:55 LAX 13:55 JFK 16:55
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86