延迟判断算法

  |  
 阅读次数

延迟判断算法

延迟判断 为了 降低 [vue,react] 框架中的, [onChange,click…] 事件

/** 组件内,函数外 缓存状态 */
this.state = {
  cacheValueArr: []
};

/** 核心思想是:
* 先缓存一次数据, 
* 定时器 2S 后 再缓存一次数据 
* 对比判断 值 是否 相等,代表没有改变
*/
onChange(e) {
  let cacheArr = this.state.cacheValueArr; // 先引用缓存的状态
  let len = cacheArr.push(e); // push方法 会返回 长度,改变原数组
  let lastOne = cacheArr.slice(-1); // 数组最后一位的 值

  setTimeout(() => {
    let lastLen = this.state.cacheValueArr.length; // 2S 后再缓存 长度有无变化
    let lastOnes = this.state.cacheValueArr.slice(-1); // 2S 后再缓存 值有无变化
    if (len === lastLen) {
      this.setState({
        curE: e
      })
      debugger
    }
  }, 2000);
}

ECharts学习笔记

  |  
 阅读次数

ECharts学习笔记

API

API分为 四大类
[‘echarts’, ‘echartsInstance’, ‘action’, ‘events’]

  • echarts

    • init: Function \
      创建一个 ECharts 实例,返回 echartsInstance,不能在单个容器上初始化多个 ECharts 实例。

      (dom, theme?, opts?) => echartsInstance

    • connect \
      多个图表实例实现联动。

    • disconnect \
      解除图表实例的联动,如果只需要移除单个实例,可以将通过将该图表实例 group 设为空。

    • dispose \
      销毁实例,实例销毁后无法再被使用。

    • getInstanceByDom \
      获取 dom 容器上的实例。

    • registerMap \
      注册可用的地图,必须在包括 geo 组件或者 map 图表类型的时候才能使用。

    • getMap \
      获取已注册的地图,返回的对象类型如下

    • registerTheme \
      注册主题,用于初始化实例的时候指定。

    • graphic \
      图形相关帮助方法。

      • clipPointsByRect
        输入一组点,和一个矩形,返回被矩形截取过的点。

      • clipRectByRect
        输入两个矩形,返回第二个矩形截取第一个矩形的结果。

      注意:如果矩形完全被截干净,会返回 undefined。

  • echartsInstance \
    通过 echarts.init 创建的实例。

    • group \
      图表的分组,用于联动

    • setOption !\
      设置图表实例的配置项以及数据,万能接口,所有参数和数据的修改都可以通过setOption完成,ECharts 会合并新的参数和数据,然后刷新图表。\
      如开启动画,ECharts 找到两组数据之间的差异然后通过合适的动画去表现数据的变化。

      注: ECharts 2.x 中的通过 addData , setSeries 方法设置配置项的方式将不再支持,在 ECharts 3 中统一使用setOption,可参考示例。

      1
      2
      3
      4
      5
      6
      7
      chart.setOption(option, notMerge, lazyUpdate);

      chart.setOption(option, {
      notMerge: ...,
      lazyUpdate: ...,
      silent: ...
      });
- getWidth \
获取 ECharts 实例容器的宽度。
() => number

- getHeight \
获取 ECharts 实例容器的高度。
() => number

- getDom \
获取 ECharts 实例容器的 dom 节点。

- getOption \
获取当前实例中维护的option对象,返回的option对象中包含了用户多次setOption合并得到的配置项和数据,也记录了用户交互的状态 \
例如图例的开关,数据区域缩放选择的范围等等。所以从这份 option 可以恢复或者得到一个新的一模一样的实例。 \
注意:返回的 option 每个组件的属性值都统一是一个`数组`,不管setOption传进来的时候是单个组件的对象还是多个组件的数组。 \
推荐通过setOption去修改部分配置。

- resize \
改变图表尺寸,在容器大小发生改变时需要手动调用。

- dispatchAction \
触发图表行为,例如图例开关`legendToggleSelect`, 数据区域缩放`dataZoom`,显示提示框`showTip`等等,更多见 `action` 和 `events` 的文档。

- on \
绑定事件处理函数。 \
ECharts 中的事件有两种,1、鼠标事件,在鼠标点击某个图形上会触发, 2、调用 dispatchAction 后触发的事件。具体见 action 和 events 的文档。 \
参数 [eventName, query]

- off \
解绑事件处理函数。 \
参数 [eventName, handler]

- convertToPixel \
转换坐标系上的点到像素坐标值。

- convertFromPixel \
转换像素坐标值到逻辑坐标系上的点。是 convertToPixel 的逆运算。 

- containPixel \
判断给定的点是否在指定的坐标系或者系列上。

- showLoading \
显示加载动画效果。可以在加载数据前手动调用改接口显示加载动画,在数据加载完成后调用 hideLoading 隐藏加载动画。

- hideLoading \
隐藏动画加载效果。

- getDataURL \
导出图表图片,返回一个 base64 的 URL,可以设置为Image的src。

- getConnectedDataURL \
导出联动的图表图片,返回一个 base64 的 url,可以设置为Image的src。导出图片中每个图表的相对位置跟容器的相对位置有关。

- appendData \
此接口用于,在大数据量(百万以上)的渲染场景,分片加载数据和增量渲染。在大数据量的场景下(例如地理数的打点),就算数据使用二进制格式,也会有几十或上百兆,在互联网环境下,往往需要分片加载。appendData 接口提供了分片加载后增量渲染的能力,渲染新加如的数据块时不会清除原有已经渲染的部分。

- clear \
清空当前实例,会移除实例中所有的组件和图表。清空后调用 getOption 方法返回一个{}空对象。

- isDisposed \
当前实例是否已经被释放。

- dispose \
销毁实例,销毁后实例无法再被使用。
  • action \
    ECharts 中支持的图表行为,通过 dispatchAction 触发。 \
    注: 代码中的 ?: 表示该属性是可选的。EVENT: 是 action 对应触发的事件。

    • highlight \
      高亮指定的数据图形。 \
      通过seriesName或者seriesIndex指定系列。如果要再指定某个数据可以再指定dataIndex或者name

    • downplay \
      取消高亮指定的数据图形。

    • legend \
      图例组件相关的行为,必须引入图例组件后才能使用。

      • legendSelect \
        选中图例。

      • legendUnSelect \
        取消选中图例。

      • legendToggleSelect \
        切换图例的选中状态。

      • legendScroll \
        控制图例的滚动。当 legend.type 为 ‘scroll’ 时有效。

    • tooltip \
      提示框组件相关的行为,必须引入提示框组件后才能使用。

      • showTip \
        显示提示框。

      • hideTip \
        隐藏提示框。

    • dataZoom \
      数据区域缩放组件相关的行为,必须引入数据区域缩放组件后才能使用。

      • dataZoom \
        数据区域缩放。
    • visualMap \
      视觉映射组件相关的行为,必须引入视觉映射组件后才能使用。

      • selectDataRange \
        选取映射的数值范围。
    • timeline \
      时间轴组件相关的行为,必须引入时间轴组件后才能使用。

      • timelineChange \
        设置当前的时间点。

      • timelinePlayChange \
        切换时间轴的播放状态。

    • toolbox \
      工具栏组件相关的行为,必须引入工具栏组件后才能使用。

      • restore \
        重置 option。
    • pie \
      饼图相关的行为,必须引入饼图后才能使用。

      • pieSelect \
        选中指定的饼图扇形。

      • pieUnSelect \
        取消选中指定的饼图扇形。

      • pieToggleSelect \
        切换指定的饼图扇形选中状态。

    • geo \
      地图组件相关的行为,必须引入地图组件后才能使用。

      • geoSelect \
        选中指定的地图区域。

      • geoUnSelect \
        取消选中指定的地图区域。

      • geoToggleSelect \
        切换指定的地图区域选中状态。

    • map \
      地图图表相关的行为,必须引入地图图表后才能使用。

      • mapSelect \
        选中指定的地图区域。

      • mapUnSelect \
        取消选中指定的地图区域。

      • mapToggleSelect \
        切换指定的地图区域选中状态。

    • graph \
      关系图 相关的行为,必须引入 关系图 后才能使用。

      • focusNodeAdjacency \
        将指定的节点以及其所有邻接节点高亮。

      • unfocusNodeAdjacency \
        将指定的节点以及其所有邻接节点高亮。

    • brush \
      区域选择相关的行为。

      • brush \
        触发此 action 可向 echarts 中添加一个或多个选框
  • events \
    在 ECharts 中主要通过 on 方法添加事件处理函数,该文档描述了所有 ECharts 的事件列表。 \
    ECharts 中的事件分为两种,一种是鼠标事件,在鼠标点击某个图形上会触发,还有一种是 调用 dispatchAction 后触发的事件。

    • 鼠标事件 \
      鼠标事件包括clickdblclickmousedownmouseupmouseovermouseoutglobaloutcontextmenu
      参见 ECharts 中的事件和行为

    • legendselectchanged \
      ACTION: legendToggleSelect 切换图例选中状态后的事件。
      注:图例组件用户切换图例开关会触发该事件。

    • legendselected \
      ACTION: legendSelect 图例选中后的事件。

    • legendunselected \
      ACTION: legendUnSelect 图例取消选中后的事件。

    • legendscroll \
      ACTION: legendscroll 图例滚动事件。

    • datazoom \
      ACTION: dataZoom
      数据区域缩放后的事件。

    • datarangeselected \
      ACTION: selectDataRange 视觉映射组件中,range 值改变后触发的事件。

    • timelinechanged \
      ACTION: timelineChange 时间轴中的时间点改变后的事件。

    • timelineplaychanged \
      ACTION: timelinePlayChange 时间轴中播放状态的切换事件。

    • restore \
      ACTION: restore 重置 option 事件。

    • dataviewchanged \
      工具栏中数据视图的修改事件。

    • magictypechanged \
      工具栏中动态类型切换的切换事件。

    • geoselectchanged \
      ACTION: geoToggleSelect \
      geo 中地图区域切换选中状态的事件。

    • geoselected \
      ACTION: geoSelect \
      geo 中地图区域选中后的事件。

    • geounselected \
      ACTION: geoUnSelect
      geo 中地图区域取消选中后的事件。

    • pieselectchanged \
      ACTION: pieToggleSelect
      series-pie 中饼图扇形切换选中状态的事件。

    • pieselected \
      ACTION: pieSelect
      series-pie 中饼图扇形选中后的事件。
      使用dispatchAction可触发此事件,用户点击不会触发此事件(用户点击事件请使用 pieselectchanged)。

    • pieunselected \
      ACTION: pieUnSelect
      series-pie 中饼图扇形取消选中后的事件。

    • mapselectchanged \
      ACTION: mapToggleSelect
      series-map 中地图区域切换选中状态的事件。
      用户点击选中会触发该事件。

    • mapselected \
      ACTION: mapSelect
      series-map 中地图区域选中后的事件。

JS设计模式

  |  
 阅读次数

第一章 灵活语言–JavaScript

1.1 全局变量 命名函数

function fnName() {}

1.2 全局变量 函数表达式

var fnName = function() {}

ps:全局变量污染全局作用域,容易被覆盖

1.3 对象收编变量

1
2
3
4
var fnObj = {
fn1: function() {},
fn2: () => {}
}

1.4 对象另一种形式

JS万事万物皆对象,函数也是对象

首先声明一个对象, 然后添加方法

1
2
var fnObj = function() {};
fnObj.fn1 = function() {};

ps: 对象不能复制, new 关键字 创建新对象,新对象不能继承方法

1.5真假对象

简单复制,将方法放在一个函数对象中

1
2
3
4
5
6
7
8
9
var fnObj = function() {
return {
fn1: function() {},
fn2: () => {}
}
}

var a = fnObj();
a.fn1();

ps: 每次调用返回新对象, 状态不会互相干扰 / 新创建对象 和 fnObj 没有任何关系

1.6 类

1.5假对象新创建对象 和fnObj没有任何关系

1
2
3
4
5
6
7
8
var fnObj = function() {
this.fn1 = function(){}
this.fn2 = () => {}
this.fn3 = arguments => {}
}

var a = new fnObj();
a.fn1();

用类创建对象

1.7 检测类

所有方法放在 函数内部 通过this定义。\
每次通过new关键字创建新对象,新对象this上的属性/方法进行复制。新创建对象 都有自己的一套方法,但是造成的消耗很奢侈。

第一种方法

1
2
3
var fnObj = function() {};
fnObj.prototype.fn1 = function() {};
fnObj.prototype.fn2 = () => {};

实例 共享prototype属性/方法

第二种方法

1
2
3
4
5
6
var fnObj = function() {};

fnObj.prototype = {
fn1: function() {},
fn2: () => {}
}

两种方法不能混用,第二种覆盖第一种.

1.8 方法的链式调用

在声明的 每个方法末尾 将当前对象返回,JS中this关键字指向当前对象

1
2
3
4
5
6
7
8
9
10
11
12
13
var fnObj = {
fn1: function() {
// DoSomeThing
return this;
},
fn2: () => {
// DoSomeThing
return this;
}
}

// 链式调用
> fnObj.fn1().fn2();

构造函数原型链式调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var fnObj = function() {};

fnObj.prototype = {
fn1: function() {
// DoSomeThing
return this;
},
fn2: () => {
// DoSomeThing
return this;
}
}

// 使用时需要先创建一下
var a = new fnObj();
a.fn1().fn2();

1.9 函数祖先

prototype.js / lodash.js, js框架;

在内置对象Function原型上添加方法

Function.prototype.fn1 = fucntion() {}

// 函数形式

var f = function() {};
f.fn1();

// 构造函数

var f = new Function();
f.fn1();

此种方法不被推荐,污染原生对象Function, 可抽象出一个 统一添加方法的 功能方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 在原型上挂载`addMethod`方法
Function.prototype.addMethod = function(name, fn) {
this[name] = fn;
}

// 两种生成实例的方法,任选其一
var methods = function() {};
||
var methods = new Function();

methods.addMethod('fn1', function() {});
methods.addMethod('fn2', function() {});

methods.fn1();
methods.fn2();

1.10链式添加

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 在原型上挂载`addMethod`方法
Function.prototype.addMethod = function(name, fn) {
this[name] = fn;
return this;
}

// 顺便支持`链式调用`
var fn = function() {};
fn.addMethod('fn1', function() {
return this;
}).addMethod('fn2', function() {
return this;
})

fn.fn1().fn2();

1.11 类式调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 在原型上挂载`addMethod`方法
Function.prototype.addMethod = function(name, fn) {
this.prototype[name] = fn;
return this;
}

// 顺便支持`链式调用`
var fn = function() {};
fn.addMethod('fn1', function() {
return this;
}).addMethod('fn2', function() {
return this;
})

// 调用时需要注意
var fns = new fn();
fns.fn1();

总结:

JS是一种灵活的语言, 函数扮演一等公民。使用JS可以编写出更多优雅的艺术代码

忆之获: 函数 多样化 创建/使用. 灵活性是语言特有气质。团队开发慎重,尽量保证团队代码风格一致。易开发、可维护、代码规范必然要求。

问答:

  • 问: 1.5真假对象 一节中如何实现方法链式调用?\
    答:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    var fnObj = function() {
    return {
    fn1: function() {
    return this;
    },
    fn2: () => {
    return this;
    }
    }
    }

    var fn = fnObj();
    fn.fn1().fn2();
  • 问:试定义一个可为函数添加多方法的addMethod方法。\
    答:参考1.10链式添加

    方式一

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    // 在原型上挂载`addMethod`方法
    Function.prototype.addMethod = function(name, fn) {
    this[name] = fn;
    return this;
    }

    // 顺便支持`链式调用`
    var fn = function() {};
    fn.addMethod('fn1', function() {
    return this;
    }).addMethod('fn2', function() {
    return this;
    })

    fn.fn1().fn2();

    方式二

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    // 定义 参数类型 接口
    interface opt = {
    fnName: string,
    fn: function
    }

    // 支持 一次性 创建多个方法
    Function.prototype.addMethod = function(options: opt[]) {
    for(obj of options) {
    this[obj.fnName] = obj.fn;
    }
    trturn this;
    }

    var methods = [
    {
    fnName: 'fn1',
    fn: function() {}
    },
    {
    fnName: 'fn2',
    fn: () => {}
    }
    ...
    ]

    var '自定义Fn' = function() {};

    '自定义Fn'.addMethod(methods);
  • 问:试定义一个既可为函数添加多方法,又可为原型添加方法的addMethod方法。\
    答:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    // 定义 参数类型 接口
    interface opt = {
    fnName: string,
    fn: function
    }

    // 支持 一次性 创建多个方法
    Function.prototype.addMethod = function(options: opt[], proto: string) {
    if(proto === "prototype") {
    for(obj of options) {
    this.protype[obj.fnName] = obj.fn;
    }
    } else {
    for(obj of options) {
    this[obj.fnName] = obj.fn;
    }
    }
    trturn this;
    }

第二章 面向对象编程

2.1 面向对象 面向过程

面向对象编程 就是 将 需求 抽象成一个对象, 针对对象分析 特征(属性) / 动作(方法). 这个对象称为.

核心思想:封装 继承 多继承 多态

2.2 包装明星–封装

2.2.1 创建一个类

首先声明一个函数,保存在一个变量里. 按编程习惯,将类名首字母大写.
然后在函数(类)内部通过对this(函数内部自带变量,用于指向当前对象)变量添加 属性/方法,实现对类添加属性/方法

1
2
3
4
5
var Book = function(id, bookName, price) {
this.id = id;
this.bookName = bookName;
this.price = price;
}

也可通过的原型(类本身也是对象,所以也有原型prototype)上添加属性/方法.\
两种方式:

①为原型对象属性赋值

1
Book.prototype.show = function() {};

②将一个对象赋值给类的原型对象.

1
2
3
4
Book.prototype = {
show: function() {},
fn2: function() {},
}

两种模式不能混用

使用时需要new关键字,实例化(创建)新对象.

关于对实例方法和原型方法解释:
通过this添加的方法/属性,是在当前对象上添加的\
JS是一种基于prototype原型的语言, 每创建一个对象(函数也是一种对象),都有一个prototype原型用于指向 其继承的 属性/方法. 通过prototype继承方法非对象自身所有,需要通过prototype逐级查找。
通过this定义的方法/属性,是对象自身拥有, 每次通过创建新对象实例时,都会复制本身方法、属性\
prototype上方法/属性是继承来,状态共享, 不会被多次创建。

2.2.2 属性与方法封装

理解:

  1. 通过JS函数作用域 实现 函数内部创建
    面向对象思想:

    属性/方法 的 隐藏、暴露, 私有属性/私有方法、公有属性/公有方法、保护属性/保护方法

JS通过函数作用域实现私有属性/私有方法;

this创建公有属性/公有方法, 通过this创建的公有方法,可以访问类(创建时)||对象私有属性/私有方法, 由于这些方法权利比较大, 又称为特权方法;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 私有属性/私有方法, 特权方法, 对象公有属性/对象公有方法, 构造器
var Book = fucntion(id, name, price) {
// 私有属性
var num = 1;
// 私有方法
function checkId() {};

// 特权方法
this.getName = function() {};
this.getPrice = function() {};
this.setName = function() {};
this.setPrice = function() {};

// 对象公有属性
this.id = id;
// 对象公有方法
this.copy = function() {};

// 构造器
this.setName(name);
this.setPrice(price);
}

理解:

  1. 通过JS函数作用域特征,来实现 函数内部创建 外部无法访问的私有变量/私有方法
  2. 通过new关键字,实例化对象时,会对执行一次,所以内部this上定义的属性/方法自然可复制到 新创建对象上,成为 对象公有属性/公有方法
  3. 其中一些方法能访问到 私有属性/私有方法, 比外界权利大,得名特权方法
  4. 通过new关键字 实例化对象 时,执行了一遍的函数,里面通过调用特权方法,初始化对象的一些属性。
  5. 外部通过 点语法 定义 属性/方法: 通过new关键字创建新对象时,由于外面通过 点语法 定义的属性/方法没有执行到,所以 新创建对象中无法获取,但可通过来使用,因此在类外面通过 点语法 定义的 属性/方法 被称为 类的静态公有属性/静态公有方法
  6. 通过prototype创建的属性/方法类实例对象中可通过this访问(新创建对象proto指向类的原型所指向的对象), 所以将prototype对象中属性/方法称为公有属性/公有方法
1
2
3
4
5
6
7
8
9
10
11
// 类静态公有属性(实例对象不能访问)
Book.isChinese = true;
// 类静态公有方法(实例对象不能访问)
Book.fn1 = function(){};

Book.prototype = {
// 公有属性
isBook: false,
// 公有方法
fn2: function() {}
}

通过new关键字创建的对象 实质 是对 新对象this的不断赋值,并将prototype指向 类的prototype 所指向的对象。

类的构造函数 外,通过点语法定义的属性/方法 是不会添加到 新创建 对象上去的。

想要在新创建对象中使用静态公有属性,得通过 类本身,不能通过this。

类的原型上定义的属性在 新对象里 可直接使用,因为 新对象 prototype和 类 的 prototype 指向同一对象

类私有属性 和 静态方法 在 实例对象中访问不到

公有属性在实例对象中可通过 点语法 访问到

2.2.3 闭包实现

类的静态变量 通过闭包实现

2.2.4 创建对象的安全模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 创建一个图书类
var Book = function(title, time, type) {
this.title = title;
this.time = time;
this.type = type;
}

// 实例化一本书
var book1 = Book('js', '2018', 'js')

console.log(book); // undefined

console.log(window.title); // js
console.log(window.time); // 2018
console.log(window.type); // js

总结:

  1. new关键字作用 可看做 对当前对象 this 不停赋值,例中 没有用new, 直接执行函数在全局作用域,this指向 全局变量window;
  2. 变量book 最终作用 得到Book类(函数)执行结果, 函数没有return语句, 变量book 得不到 Book类 的返回值, 遂为 undefined

安全模式 || 检察长模式

1
2
3
4
5
6
7
8
9
10
11
var Book = function(title, time, type) {
// 判断执行过程中 this 是否为 当前对象(为true说明是用 new关键字 创建)
if(this instanceof Book){
this.title = title;
this.time = time;
this.type = type;
} else {
// 否则重新创建对象并返回
return new Book(title, time, type);
}
}

总结:
每个类有 3部分

  1. 第一部分是构造函数内,供实例化对象复制
  2. 第二部分是构造函数外,直接通过点语法添加,供类直接使用,实例化对象访问不到
  3. 第三部分是类的原型中,实例化对象可通过原型链间接访问,为所有实例化对象共用

2.3 继承

2.3.1 子类原型对象–类式继承

类式继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 声明父类
function SuperClass() {
this.superValue = true;
};

// 为父类添加公有方法
SuperClass.prototype.getSuperValue = function() {
return this.superValue;
};

// 声明子类
function SubClass() {
this.subValue = false;
}

// 继承父类
SubClass.prototype = new SuperClass();
// 先继承,再为子类添加公有方法
SubClass.prototype.getSubValue = function() {
return this.subValue;
}

// 以上 类似`封装`的过程

总结:
类式继承 需要将 第一个类的实例 赋值给 第二个 类的原型\
类的原型对象 作用是 为类的原型添加公有方法,类不能直接访问原型中的属性/方法,必须通过 原型prototype 来访问。\
实例化一个父类时,新创建对象复制了父类构造函数内 属性/方法, 并且将 原型proto 指向父类原型对象, 如此便拥有 父类 原型对象/构造函数 上 属性/方法,

instanceof判断对象继承关系\
instanceof通过判断对象prototype链来确定对象是否为某类实例,不关心对象自身结构

console.log(obj instanceof Class); // true
console.log(SubClass instanceof ParentClass); // false

instanceof 判断 前面对象是否为 后面 类(对象)实例,不表示两者的继承\
子类 继承 父类 时通过将 父类实例 赋值给 子类原型prototype, 子类原型 继承 父类

console.log(SubClass.prototype instanceof ParentClass); // true

所有对象都继承自Object原生对象构造函数

console.log(allObj instanceof Object); // true

类式继承缺点

  1. 子类通过原型prototype父类实例化, 继承父类。

十一学习记录

  |  
 阅读次数

第一天

复习昨日下午组长培训内容

  1. 组件中定义两个方法

    mapStateToProps // 函数、方法, 把Redux状态树store对象 中数据 遍历赋值 到 当前挂载组件props
    mapDispatchToProps // 派发方法 到 当前挂载组件props

关于架构设计

  |  
 阅读次数

架构设计

架构设计的主要目的
解决复杂度带来的问题

架构复杂度来源

  1. 孜孜不倦追求 高性能\
    所有性能提高的背后,都是方法的优化系统复杂度的提高

  2. 防止意外的高可用\
    系统高可用 本质通过冗余,水多加面,面多加水

  3. 应对变化的可拓展\
    保障在不重构的情况下,为需求变化提供实现可能

高性能、高可用性、可拓展,是架构师工作着重考虑缓解,三点直接作用于 架构设计内部

同样要注意 外部环境 对架构设计影响,比如安全性成本规模

找出业务场景短板

面对实际业务场景

第一步 分析并确定架构方向

需要 高可用? 高性能? 可扩展? 安全?

第二步 准备几套备用方案

开发 运维等部门讨论,选择针对实际情况最优方案

虚拟场景

前浪微博 中间件 团队 6人
整体熟悉 JAVA,一人 C/C++
开发平台 Linux
数据库 MySQL
业务系统 单机房部署

p.s: 发展快 系统协作效率低 各子系统 通过接口调用 出现问题 难定位

架构设计问题根源 在于 各个业务 子系统 强耦合, 信息列队系统 可满足 子系统 解耦

架构难在哪里?

难在灵活多变。高性能、高可用、可拓展、安全性、规模 等, 不可能样样兼顾

判断复杂度

对关键点 分权重

  1. 是否需要高性能?\
    目前,发展趋势,预留系统容量 应对 未来业务增长。设计目标定为现在峰值4倍 较为合理

  2. 是否需要高可用?\
    信息审核、用户服务 是社交媒体 关键业务。信息列队 需要 高可用性,包括 信息写入、消息储存、消息读取

  3. 是否需要高扩展?\
    本虚拟场景 前浪微博 消息列队 功能明确,基本无须拓展

初步设计备选方案,分析优缺点

综上,前浪微博 信息列队系统 需要 高性能 消息读取、高可用 消息写入、高可用 消息存储和读取

3种备选方案

  1. 开源Kafka 本身是 成熟的开源信息列队方案,性能好
  2. 集群 + MySQL存储。采用 数据分散集群架构,省略
  3. 集群 + 自研存储方案