React - 修改children(下)

React - 修改children(上) 中我提到了React在遍历children过程中是不允许修改其中的React Element的,这里我要做点补充,就是有个前提是:使用的React是非压缩版的,也就是说不是使用react.min.js这种,使用react.min.js则不会报错。

查看React非压缩版的源码发现,里边有许多这样的代码块,而在压缩版中是没有的。

if ("development" !== 'production') {
  ......
}

举个例子 React v0.14.4 (注释被我去掉了)

  • react.js

var ReactElement = function (type, key, ref, self, source, owner, props) {
  var element = {
    $$typeof: REACT_ELEMENT_TYPE,
    type: type,
    key: key,
    ref: ref,
    props: props,
    _owner: owner
  };

  if ("development" !== 'production') {
    ......
    Object.freeze(element.props);
    Object.freeze(element);
  }

  return element;
};
  • react.min.js

u = function(e, t, n, r, o, i, u) {
  var s = {
    $$typeof: a,
    type: e,
    key: t,
    ref: n,
    props: u,
    _owner: i
  };
  return s
};

对比压缩前后,由if ("development" !== 'production') {} 包裹的代码块被直接strip掉了,说明压缩工具确实了得。
这里重点是看压缩前的,有两行代码很关键:

Object.freeze(element.props);
Object.freeze(element);

查看一下MDN关于Object.freeze的介绍:
The Object.freeze() method freezes an object: that is, prevents new properties from being added to it; prevents existing properties from being removed; and prevents existing properties, or their enumerability, configurability, or writability, from being changed. In essence the object is made effectively immutable. The method returns the object being frozen.
意思是说freeze防止了对象被修改,包括增删改属性。倘若在freeze之后修改对象属性,会有两种结果:
1若在非strict mode下,不会报错,但是任何修改都是不起作用的。
2若在strict mode 下,会throw TypeErrors。

看到这里可以知道,为啥在使用非压缩版的时候修改React Element时会提示报错,正是因为该对象被freeze了;相反在压缩版中因为没有freeze,所以能够成功修改,不会报错。

谈到这里再顺便提下两点:

  • 压缩时怎么把if ("development" !== 'production') {} 去掉的?
    React的README提及到:

To use React in production mode, set the environment variable NODE_ENV to production. A minifier that performs dead-code elimination such as UglifyJS is recommended to completely remove the extra code present in development mode.
知道UglifyJS的朋友应该知道,UglifyJS在压缩中,如果遇到if的条件是可预计得到的常数结果,那么就会忽略掉没用的if/else分支。所以 "development" !== 'production' 即 false在压缩时候就被清理掉了。
UglifyJS详细的压缩规则介绍看这里:解读UglifyJS(四)

  • 为啥在开发环境下要使用Object.freeze(),引stackoverflow中Sean Vieira的一句话:
    We use Object.freeze to freeze the router and route objects for non-production environments to ensure the immutability of these objects.

在开发过程中提示报错,在线上环境不提示,有点JAVA编译的味道,编译时校验信息,提示警告和错误,在执行中不校验。
另外,Object.freeze()运行相对较慢,所以线上去掉这个操作也是为了提高性能。
freeze vs seal vs normal 这个链接有测试的栗子。

总结:开发过程中还是用非压缩版的React好,有利于及时发现问题。
完成!!!


Web开发
在学习Web前端的过程中,不管是解开了的纠结的问题,或者从其他高手学习到的知识点,也或者是自己动手创...
307 声望
27 粉丝
0 条评论
推荐阅读
协同开发
同一个开发项目中如果有多名程序猿,那么每个程序猿都有责任培养自己协同开发的意识,为的是代码的质量,质量,质量(重要的事情说三遍!!!)。协同开发是个挖坑和填坑的过程,自己做的好可以尽量避免自己挖坑...

zhoushx3阅读 3.4k

从零搭建 Node.js 企业级 Web 服务器(零):静态服务
过去 5 年,我前后在菜鸟网络和蚂蚁金服做开发工作,一方面支撑业务团队开发各类业务系统,另一方面在自己的技术团队做基础技术建设。期间借着 Node.js 的锋芒做了不少 Web 系统,有的至今生气蓬勃、有的早已夭折...

乌柏木143阅读 12k评论 10

从零搭建 Node.js 企业级 Web 服务器(十五):总结与展望
总结截止到本章 “从零搭建 Node.js 企业级 Web 服务器” 主题共计 16 章内容就更新完毕了,回顾第零章曾写道:搭建一个 Node.js 企业级 Web 服务器并非难事,只是必须做好几个关键事项这几件必须做好的关键事项就...

乌柏木60阅读 6k评论 16

再也不学AJAX了!(二)使用AJAX ① XMLHttpRequest
「再也不学 AJAX 了」是一个以 AJAX 为主题的系列文章,希望读者通过阅读本系列文章,能够对 AJAX 技术有更加深入的认识和理解,从此能够再也不用专门学习 AJAX。本篇文章为该系列的第二篇,最近更新于 2023 年 1...

libinfs39阅读 6.2k评论 12

封面图
从零搭建 Node.js 企业级 Web 服务器(一):接口与分层
分层规范从本章起,正式进入企业级 Web 服务器核心内容。通常,一块完整的业务逻辑是由视图层、控制层、服务层、模型层共同定义与实现的,如下图:从上至下,抽象层次逐渐加深。从下至上,业务细节逐渐清晰。视图...

乌柏木39阅读 7.1k评论 6

【关于Javascript】--- 正则表达式篇
基础知识一、元字符 {代码...} 二、量词 {代码...} 三、集合 字符类 {代码...} 四、分支 {代码...} 五、边界 开始结束 {代码...} 六、修饰符 {代码...} 七、贪婪模式和非贪婪模式js默认贪婪模式即最大可能的匹配...

Jerry35阅读 2.9k

从零搭建 Node.js 企业级 Web 服务器(二):校验
校验就是对输入条件的约束,避免无效的输入引起异常。Web 系统的用户输入主要为编辑与提交各类表单,一方面校验要做在编辑表单字段与提交的时候,另一方面接收表单的接口也要做足校验行为,通过前后端共同控制输...

乌柏木32阅读 6.1k评论 9

307 声望
27 粉丝
宣传栏