一、什么是高阶函数(组件),作用是什么?

子类使用父类的方法可以通过继承的方式实现,那无关联组件通信(redux)、父类使用子类方法(反向继承)呢

为了解决类(函数)功能交叉/功能复用等问题,通过传入类/函数返回类/函数(继承)的方式使得类拥有自身未定义的方法。

例如react-redux的connect方法使用了高阶组件:

React Redux的connect:

  1. const HOC = connnect(mapStateToProps)(Comp);
  2. // connect为柯里化函数 实际为 =>
  3. function connect(mapStateToProps) {
  4. // ...
  5. return function(Comp) {
  6. // ...
  7. }
  8. }
  9. // 使用箭头函数则为
  10. const connect = mapStateToProps => Comp => {...};

二、通过高阶函数实现两个无关函数的通信

需求介绍

存在一个类SubClass(子类),该类范围内有数据state对象,且有setState和getState两个函数方法。现在希望通过SupClass1(超/父类1)去调用SubClass(子类)的setState方法,并在SupClass2(超/父类2)里通过getState方法输出结果。

注意,子为sub,父为sup

文件目录

  1. ├── SubClass.js # 子类
  2. ├── SupClass1.js # 父类1
  3. ├── SupClass2.js # 父类2
  4. ├── index.html

SubClass类增加数据state,并赋予查询修改的能力

  1. // SubClass.js
  2. class SubClass {
  3. constructor(args = {}) {
  4. this.state = {
  5. ...args,
  6. };
  7. }
  8. // 赋值时需要提供键和值
  9. setState = (key, val) => {
  10. this.state = {
  11. [key]: val,
  12. };
  13. };
  14. getState = (key) => {
  15. if (key in this.state) {
  16. return this.state[key];
  17. }
  18. // 当然我们希望严谨点
  19. const err = '无效key值';
  20. throw err;
  21. };
  22. }

我们试试SubClass功能如何

  1. // index.html
  2. const subcls = new SubClass({name: 'xiaobe'});
  3. const res = subCls.getState('name');
  4. console.log('res', res);
  5. // 输出xiaobe,妥妥的

接下来我们给SupClass1赋予setState的能力

  1. class SuperClass1 {
  2. set(key, val) {
  3. // SuperClass1里没有setState方法!
  4. this.setState(key, val);
  5. }
  6. }

如果直接执行类里的get方法肯定是会出错的。所以我们需要先对SupClass1做点事情。

需要给SuperClass1类里增加方法setState,可以使用继承

  1. // SuperClass1.js
  2. class SuperClass1 extends SubClass {
  3. constructor(props) {
  4. super(props);
  5. }
  6. set(key, val) {
  7. // 父类1上使用子类的setState方法
  8. this.setState(key, val);
  9. }
  10. }
  11. // index.html
  12. const supCls1 = new SuperClass1({name: 'sup-xiaobe'});
  13. const res = supCls1.getState('name');
  14. console.log(res);
  15. // 也能输出sup-xiaobe

但如果单纯使用继承的方式会造成很多的麻烦。例如子类和父类如果有同名方法,默认子类会覆盖基类(父类的其他叫法)的同名方法,如果基类方法使用了函数绑定或箭头函数,其this的指向就改变了,指向了基类,导致自身同名方法失效。

因此我们还是需要通过高阶组件实现;

首先我们先给子类SubClass增加一个HOC入口

  1. class SubClass {
  2. // ...
  3. HOC(cls) {
  4. // 需要调用SubClass类的方法,所以需要存一份其this
  5. const sub_this = this;
  6. // 父类除了以下新增的两个方法,其他无任何变化地返回!
  7. return class extends cls {
  8. constructor(props) {
  9. super(props);
  10. // 此处this指向该子类,sub_this指向SubClass类
  11. this.getState = sub_this.getState;
  12. this.setState = sub_this.setState;
  13. }
  14. }
  15. }
  16. // ...
  17. }

接着我们来父类1SupClass1实例化前升级(调用HOC)!

  1. // index.html
  2. const subCls = new SubClass();
  3. // 在子类实例化后给父类加上HOC方法
  4. const supClsHoc1 = subCls.HOC(SuperClass1);
  5. // 实例化父类
  6. const supCls1 = new supClsHoc1();
  7. // 重新定义state.name
  8. supCls1.set('name', 'sup-xiaobe');
  9. console.log(supCls.getState('name'));
  10. // 输出sup-xiaobe

同理地完成SupClass2

  1. // SupClass2.js
  2. class SuperClass2 {
  3. get(key) {
  4. return this.getState(key);
  5. }
  6. }
  7. // 最终的index.html
  8. const subCls = new SubClass({name: 'xiaobe'});
  9. const supClsHoc1 = subCls.HOC(SuperClass1);
  10. const supClsHoc2 = subCls.HOC(SuperClass2);
  11. const supCls1 = new supClsHoc1();
  12. const supCls2 = new supClsHoc2();
  13. supCls1.set('name', 'sup-xiaobe');
  14. const res = supCls2.get('name');
  15. console.log('res', res);

这么一个基础简单的组件通信就完成了。

根据这个思路可以封装一个类似全局变量的Store.js

思考个问题

高阶函数HOF和高阶组件HOC(Higher Order Func/Comp)的更多相关文章

  1. 高阶函数 HOF & 高阶组件 HOC

    高阶函数 HOF & 高阶组件 HOC 高阶类 js HOC 高阶函数 HOF 函数作为参数 函数作为返回值 "use strict"; /** * * @author x ...

  2. Kotlin的高阶函数和常用高阶函数

    Kotlin的高阶函数和常用高阶函数 文章来源:企鹅号 - Android先生 高阶函数的定义 将函数当做参数或者是返回值的函数 什么是高阶函数 可以看看我们常用的 函数: 首先我们可以知道, 是 的 ...

  3. 高阶组件&&高阶函数(一)

    antd里面的form表单方面,遇到一个高阶函数,以及高阶组件,于是看了一下这方面内容,前辈们的文章写得也非常详细,这里就稍微kobe一下 高阶函数与高阶组件 高阶函数: 高阶函数,是一种特别的函数, ...

  4. JavaScript ES6函数式编程(一):闭包与高阶函数

    函数式编程的历史 函数的第一原则是要小,第二原则则是要更小 -- ROBERT C. MARTIN 解释一下上面那句话,就是我们常说的一个函数只做一件事,比如:将字符串首字母和尾字母都改成大写,我们此 ...

  5. React.js高阶函数的定义与使用

    /* 高阶函数的简单定义与使用 一: 先定义一个普通组件 二: 用function higherOrder(WrappendComponent) { return } 将组件包裹起来,并用export ...

  6. React事件处理、收集表单数据、高阶函数

    3.React事件处理.收集表单数据.高阶函数 3.1事件处理 class Demo extends React.Component { /* 1. 通过onXxx属性指定事件处理函数(注意大小写) ...

  7. [Effective JavaScript 笔记]第19条:熟练掌握高阶函数

    高阶函数介绍 高阶函数曾经是函数式编程的一个概念,感觉是很高深的术语.但开发简洁优雅的函数可以使代码更加简单明了.过去几年中脚本语言采用了这些个技术,揭开了函数式编程的最佳惯用法的神秘面纱.高阶函数就 ...

  8. C#函数式编程-高阶函数

    随笔分类 -函数式编程 C#函数式编程之标准高阶函数 2015-01-27 09:20 by y-z-f, 344 阅读, 收藏, 编辑 何为高阶函数 大家可能对这个名词并不熟悉,但是这个名词所表达的 ...

  9. Javascript 闭包与高阶函数 ( 一 )

    上个月,淡丶无欲 让我写一期关于 闭包 的随笔,其实惭愧,我对闭包也是略知一二 ,不能给出一个很好的解释,担心自己讲不出个所以然来. 所以带着学习的目的来写一写,如有错误,忘不吝赐教 . 为什么要有闭 ...

随机推荐

  1. TensorFlow 池化层

    在 TensorFlow 中使用池化层 在下面的练习中,你需要设定池化层的大小,strides,以及相应的 padding.你可以参考 tf.nn.max_pool().Padding 与卷积 pad ...

  2. 模板—v-dcc缩点

    int dfn[MAXN],low[MAXN],num,root; int stack[MAXN],top,cnt; bool iscut[MAXN]; int new_id[MAXN],c[MAXN ...

  3. uni-app禁止滑动穿透

    <view class="topWrapper" v-show="chooseShow" @click="chooseShow = false& ...

  4. Linux 运算符

    布尔运算符 下表列出了常用的布尔运算符,假定变量a为10 变量b为20: 运算符  说明 举例 ! 非运算 , 表达式为true 则返回false 否则返回true  [!false] 返回true. ...

  5. LRJ-Example-06-01-Uva210

    #define _CRT_SECURE_NO_WARNINGS #include <cstdio> #include <cstdlib> #include <cstrin ...

  6. Mysql错误:#1054 - Unknown column 'id' in 'field list' 解决办法

    第一次用mysql,在插入数据时,竟然报这样的错误, #1054 - Unknown column 'id' in 'field list'

  7. [C#] 汉字转拼音,支持多音字

    这份代码大概不是严格意义上正确的,但是一般场景用用应该没问题. using System; using System.Collections.Generic; using System.Linq; u ...

  8. MVC4 变更模板

    模板位置: C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\ItemTemplates\CSharp\Web\MVC 4 ...

  9. H3C CSMA/CD载波侦听

  10. javascript 变量的提升

    下面是一个关于全局和局部作用域的问题 var a = 123; function f(){ alert(a); var a = 1; alert(a); } f(); 大家第一眼看到后都会认为第一次a ...