封面
今天我们不会讨论 Angular 和 React 谁是老大问题, 而是讨论在 React 和 Angular 框架中使用到共同点.
react_vs_angular.jpeg
这些 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:`
- <h1>{{title}} tuts </h1>
- <h2>author {{name}} </h2>
- `
- })
- 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(
- [
- <h1>{{title}} tuts </h1>
- <h2>author {{name}} </h2>
- ]
- )
- }
- }
- props:{
- children:"optimized code in js"
- }
- props:{
- children:"zidea"
- }
- function updateNode(node,...){
- let value = node.property;
- }
Fibre nodes 和 view nodes 分别在 Angular 和 React 都是用来表示框架中模板, 都是用于介于 DOM 元素和模板组件之间. 接下来看看这两种数据结构有什么共同点, 他们都在框架处理更新时, 会被经常使用.
Chrome-V8-v65.jpeg
组件
图
如此做的原因何在, 也就是为什么做的这么复杂的, 答案是因为一些叫做 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 };
图
因为这些对象都具有相同结构 (布局) 我们就可以把这些共性东西抽取出来用 shape 来表示. 这也就是说明即使我们有很多对象, 我们也只是描述一次即可.
图
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 = 9 b.z = 10
图
可以想象不断为对象添加许属性, 并修改对象 shape (形状), 则可能会有一个具有数百个中间过渡的 shape(形状). 这样每次访问对象某个属性时, 虚拟机都必须经历所有这些过程, 以找出描述该属性的布局和内存的形状来检索该信息. 所以 V8 使用的一种技术是使这个过程更快..
图
图
每个 JavaScript 函数在内部都表示为名为 closure 的对象. 这是虚拟机缓存有关函数的一些信息的地方, 这些对象用于向该函数添加参数, 以及其他信息.. 这是虚拟机将缓存某些信息的位置.
function getX(o){ return o.x }
下面通过以例子来介绍其如何运行的. 假设调用 getX 函数, 并传入一个具有 x 属性的对象. 虚拟机将计算出这个对象的 shape (形状), 虚拟机可以缓存对象的 shape (形状), 随后当访问这个对象的 x 属性, 可以记录下 offset (偏移量), 当下次接受相同 shape 的对象来执行函数时, 虚拟机只需比较 shape(形状), 如果匹配, 就不再需要计算出对象 shape(形状).
图
可以从缓存中获取 offset (偏移量)值, 来解析内存中的值. 还定义了函数的状态, 状态可以有三种类型: 单态, 单态属性访问和多态. 在这种情况下, 是单态的, 是单态的表示只具有一种形状. 多态性是指一个函数被调用对象类型每一次并不相同, 而 megamorphic 是指当输入不同 shape (形状)的对象作为参数时, 通常操作四种类型的 shape 形状.
对象输入给一个函数, 以使 state (状态)保持单态是很重要的. 单态属性访问的速度可以比 megamorphic 快 100 倍.
如果考虑到在每一个更新检测周期中, 每秒可能发生几百次的 10000 次访问, 可以想象访问单态属性对速度的影响会有多大. 所以要求对象使用相同的 shape (形状), 对 fibre 和 view nodes 使用相同的隐藏类, 为了是确保属性访问是单态的. 你可以有 html 元素, 子对象, 如果遵循面向对象的编程原则, 会为不同的元素创建不同的类. 这些框架实际上将所有内容合并为一个数据结构, 一个类好处可想而知.
Fiber node(react) | Template element | View node(Angular) |
---|---|---|
HostComponent | HTMLElementNode | TypeElement |
HostText | HTMLTextNode | TypeText |
FunctionComponent, \nClassComponent | Component | Component |
最后希望大家关注我们微信公众号
wechat.jpeg
来源: http://www.jianshu.com/p/4b9072877474