angular 定义对象_速递 Angular 和 React 背后的秘密(上)

17fca2e3c33b6c18b347ebd2b6c994f4.png

今天我们不会讨论 Angular 和 React 谁是老大问题,而是讨论在 React 和 Angular 框架中使用到共同点。

61c2628c6b52f4d7eb28ee97358ba5f4.png

这些 Angular 和 React 都有共同点分别是

  • Monomorphism
  • Bit fields
  • Bloom filters

分三次分享我们把他们一一给您解释清楚。

Monomorphism

we use one type for all View nodes so that property access in loops stay monomorphic
Misko Hevery, technical lead of Angular

Fiber node ... shares the same hidden class.Never add fields outside of construction in ReactFiber
sebastian Markbage technical lead of React

调试代码时,偶尔会查看一下框架中实现原理,在 Angular 和 React 源码看到了他们框架技术负责人的注释。这些注释中不约而同谈到隐藏类(hidden class),这种框架内部的数据结构在 Angular 和 React 分别叫做 Fiber node 和 View nodes。确保这些内部的数据结构共享同一个隐藏类,也就是说使属性访问成为单态的(monomorphic)。他们为什么要这么做,这么做有什么好处是今天我们要讨论的内容。

在 Angular 中 View nodes 和数据结构来表示模板。定义了呈现 DOM 所需的元数据,还指定了 DOM 的哪个部分需要更新。

同样在 React 中定义了组件,定义了模板时, React 也使用了 fibre nodes。这是新的React fibre 16 架构。

@Component({    template:`    

{{title}} tuts

author {{name}}

`})export class AppComponent { title = 'optimized code in js'; name='zidea'}bindings:{ text:'optimized code in js'}bindings:{ text:"zidea"}class App extends Component{ state = { title = 'optimized code in js', name='zidea' }; render(){ return( [

{{title}} tuts

author {{name}}

] ) }}props:{ children:"optimized code in js"}props:{ children:"zidea"}function updateNode(node,...){ let value = node.property;}

Fibre nodes 和 view nodes 分别在 Angular 和 React 都是用来表示框架中模板,都是用于介于 DOM 元素和模板组件之间。接下来看看这两种数据结构有什么共同点,他们都在框架处理更新时,会被经常使用。

9f65c38798aaac01eb333b04a56eeabc.png
c0b0223870ac5d641d9c0d8ec29e12c6.png
aa13e6f9da886ff03e580ceb1b7ac473.png

如此做的原因何在,也就是为什么做的这么复杂的,答案是因为一些叫做shape(形状)或 hidden class (隐藏类)的东西。这正是 Sebastian 在注释中提到的隐藏类。每天在写 javascript 时,javascript 对象(object) 在虚拟机内部表现为 shape 对象,因此 shape 定义了用于描述对象的属性,如何分配内存(layout).例如 用于在内存中查找的 offset(偏移)值。可能你会问为什么我们需要 shape,为什么不直接将这些属性定义对象上 。其实这样做是有好处的,可以节省内存空间,我们可能有两对象(object),甚至更多,成千上万的对象。

let a  = {x:5,y:6};let b  = {x:7,y:8};
0d0ce1aac1e578c0f003d1479be49c31.png

因为这些对象都具有相同结构(布局)我们就可以把这些共性东西抽取出来用 shape 来表示。这也就是说明即使我们有很多对象,我们也只是描述一次即可。

d42896eaeaa6f0889ea29a425b7fa4b4.png
let a  = {x:5,y:6};let b  = {x:7,y:8};b.w = 9

如果需要对象 b 进行扩展属性 w 赋值 9,我们就需要引入新的 shape 。我们无法将 w 引入到原有 shape,因为 a 对象还依赖于 shape 而 a 并没有新增属性。所以需要引入新的 shape 并且更新他们之间关系。

let a  = {x:5,y:6};let b  = {x:7,y:8};b.w = 9b.z = 10
953ba1c78efa8576af70370480ae0e58.png

可以想象不断为对象添加许属性,并修改对象 shape (形状),则可能会有一个具有数百个中间过渡的 shape(形状)。这样每次访问对象某个属性时,虚拟机都必须经历所有这些过程,以找出描述该属性的布局和内存的形状来检索该信息。所以 V8 使用的一种技术是使这个过程更快。.

2a82b3d32f7157841abe26f852d441e1.png
613981679572d3727a1d85c27fe87c56.png

每个 JavaScript 函数在内部都表示为名为 closure 的对象。这是虚拟机缓存有关函数的一些信息的地方,这些对象用于向该函数添加参数,以及其他信息。。这是虚拟机将缓存某些信息的位置。

function getX(o){    return o.x}

下面通过以例子来介绍其如何运行的。假设调用 getX函数,并传入一个具有 x 属性的对象。虚拟机将计算出这个对象的 shape (形状),虚拟机可以缓存对象的 shape (形状),随后当访问这个对象的 x 属性,可以记录下 offset (偏移量),当下次接受相同 shape 的对象来执行函数时,虚拟机只需比较 shape(形状),如果匹配,就不再需要计算出对象 shape(形状)。

1e947e2bdc7a068a68b822ea2ea20a0d.png

可以从缓存中获取 offset (偏移量)值,来解析内存中的值。还定义了函数的状态,状态可以有三种类型:单态、单态属性访问和多态。在这种情况下,是单态的,是单态的表示只具有一种形状。多态性是指一个函数被调用对象类型每一次并不相同,而 megamorphic 是指当输入不同 shape (形状)的对象作为参数时,通常操作四种类型的 shape 形状。

对象输入给一个函数,以使 state (状态)保持单态是很重要的。单态属性访问的速度可以比megamorphic 快 100 倍。

如果考虑到在每一个更新检测周期中,每秒可能发生几百次的10000 次访问,可以想象访问单态属性对速度的影响会有多大。所以要求对象使用相同的 shape (形状),对 fibre和view nodes 使用相同的隐藏类,为了是确保属性访问是单态的。你可以有 HTML 元素,子对象,如果遵循面向对象的编程原则,会为不同的元素创建不同的类。这些框架实际上将所有内容合并为一个数据结构、一个类好处可想而知。

3b0903d4e628592b1389e4a55a07d909.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值