博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
精读《React 的多态性》
阅读量:6944 次
发布时间:2019-06-27

本文共 2679 字,大约阅读时间需要 8 分钟。

1 引言

本周精读的文章是:,看看作者是如何解释这个多态性含义的。

读完文章才发现,文章标题改为 Redux 的多态性更妥当,因为整篇文章都在说 Redux,而 Redux 使用场景不局限于 React。

2 概述

Redux immutable 特性可能产生浏览器无法优化的性能问题,也就是浏览器无法做 ,也就是上一篇精读《JS 引擎基础之 Shapes and Inline Caches》 里提到的。

先看看普通的 redux 的 reducer:

const todo = (state = {}, action) => {  switch (action.type) {    case "ADD_TODO":      return {        id: action.id,        text: action.text,        completed: false      };    case "TOGGLE_TODO":      if (state.id !== action.id) {        return state;      }      return Object.assign({}, state, {        completed: !state.completed      });    default:      return state;  }};复制代码

我们简化一下使用场景,假设基于这个 reducer todo,生成了两个新 store s1 s2

const s1 = todo(  {},  {    type: "ADD_TODO",    id: 1,    text: "Finish blog post"  });const s2 = todo(s1, {  type: "TOGGLE_TODO",  id: 1});复制代码

看上去很常见,也的确如此,我们每次 dispatch 都会根据 reducer 生成新的 store 树,而且是一个新的对象。然而对 js 引擎而言,这样的代码可能做不了 Shapes 优化(关于 Shapes 优化建议阅读上一期精读 ),也就是最需要做优化的全局 store,在生成新 store 时无法被浏览器优化,这个问题很容易被忽视,但的确影响不小。

至于为什么会阻止 js 引擎的 shapes 优化,看下面的代码:

// transition-trees.jslet a = {
x:1, y:2, z:3};let b = {};b.x = 1;b.y = 2;b.z = 3;console.log("a is", a);console.log("b is", b);console.log("a and b have same map:", %HaveSameMap(a, b));复制代码

通过 node --allow-natives-syntax test.js 执行,通过调用 node 原生函数 %HaveSameMap 判断这种情况下 ab 是否共享一个 shape(v8 引擎的 Shape 实现称为 Map)。

image

结果是 false,也就是 js 引擎无法对 a b 做 Shapes 优化,这是因为 ab 对象初始化的方式不同。

同样,在 Redux 代码中常用的 Object.assign 也有这个问题:

image

因为新的对象以 {} 空对象作为最初状态,js 引擎会为新对象创建 Empty Shape,这与原对象的 Shape 一定不同。

顺带一提 es6 的解构语法也存在同样的问题,因为 babel 将解构最终解析为 Object.assign

image

对这种尴尬的情况,作者的建议是对所有对象赋值时都是用 Object.assign 以保证 js 引擎可以做 Shapes 优化:

let a = Object.assign({}, {
x:1, y:2, z:3});let b = Object.assign({}, a);console.log("a is", a);console.log("b is", b);console.log("a and b have same map:", %HaveSameMap(a, b)); // true复制代码

3 精读

这篇文章需要与上一篇 连起来看容易理解。

作者描述的性能问题是引擎级别的 Shapes 优化问题,读过上篇精读就很容易知道,只有相同初始化方式的对象才被 js 引擎做优化,而 Redux 频繁生成的 immutable 全局 store 是否能被优化呢?答案是“往往不能”,因为 immutable 赋值问题,我们往往采用 Object.assign 或者解构方式赋值,这种方式产生的新对象与原对象的 Shape 不同,导致 Shape 无法复用。

这里解释一下疑惑,为什么说 immutable 对象之间也要优化呢?这不是两个不同的引用吗?这是因为 js 引擎级别的 Shapes 优化就是针对不同引用的对象,将对象的结构:Shape 与数据分离开,这样可以大幅优化存储效率,对数组也一样,上一篇精读有详细介绍。

所以笔者更推荐使用比如 这种库操作 immutable 对象,而不是 Object.assign,因为封装库内部是可能通过统一对象初始化方式利用 js 引擎进行优化的。

4 总结

原文提到的多态是指多个相同结构对象,被拆分成了多个 Shape;而单态是指这些对象可以被一个 Shape 复用。

笔者以前也经历过从 Object.assign 到 Immutablejs 库,最后又回到解构新语法的经历,觉得在层级不深情况下解构语法可以代替 Immutablejs 库。

通过最近两篇精读的分析,我们需要重新思考这样做带来的优缺点,因为在 js 环境中,Object.assign 的优化效率比 Immutablejs 库更低。

最后,也完全没必要现在就开始重构,因为这只是 js 运行环境中很小一部分影响因素,比如为了引入 Immutablejs 让你的网络延时增加了 100%?所以仅在有必要的时候优化它。

5 更多讨论

讨论地址是:

如果你想参与讨论,请,每周都有新的主题,周末或周一发布。

原文发布时间为:2018年07月02日

本文作者:黄子毅
本文来源:
 如需转载请联系原作者
你可能感兴趣的文章
可编辑ztree节点的增删改功能图标控制---已解决
查看>>
Android-自己定义标题栏
查看>>
C# Winform利用POST传值方式模拟表单提交数据(Winform与网页交互)
查看>>
LeetCode【8】. String to Integer (atoi) --java实现
查看>>
微信小程序开发教程目录
查看>>
Java进阶路线图
查看>>
C - The C Answer (2nd Edition) - Exercise 1-4
查看>>
java基本类型(数值范围):浮点的底层表示定义,float计算快一些
查看>>
[React Native] change port when running react native
查看>>
[转] 利用BLKTRACE分析IO性能
查看>>
easyui combobox下拉列表的多选值
查看>>
Xamarin iOS教程之编辑界面编写代码
查看>>
H5 和移动端 WebView 缓存机制解析与实战
查看>>
ORA-38760: This database instance failed to turn on flashback database
查看>>
【DB】MYSQL相关细节
查看>>
C#中的反射
查看>>
一个三年Android开发的总结-开篇
查看>>
atitit.基于http json api 接口设计 最佳实践 总结o7
查看>>
【树莓派】做一个备份镜像
查看>>
Sqlserver 2016 R Service环境安装的各种错误(坑)解决办法
查看>>