Live Note

Remain optimistic

extends Array

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class PowerArray extends Array {
isEmpty() {
return this.length === 0;
}

// filter/map/... 等函数不再传递PowerArray
static get [Symbol.species] () {
return Array;
}
}

let arr = new PowerArray(1, 2, 3);
alert(arr.isEmpty()); // false

let filter_array = arr.filter(i => i > 1);
alert(filter_array.isEmpty()); //Error

扩展运算符

1
2
3
4
5
6
7
8
9
10
11
console.log(...[1, 2, 3]) //1 2 3
console.log(1, ...[2, 3], 4) //1 2 3 4
;[...document.querySelectorAll("div")] //[<div>, <div>, ...];

function add(x, y) {
return x + y
}
add(...[1, 2]) //3

//与表达式一同使用
const arr = [...(x > 0 ? ["a"] : []), "b"]

扩展运算符的应用

  • 替代数组的 apply 方法

    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
    function f(x, y, z) {}
    var args = [0, 1, 2]

    //ES5 写法
    f.apply(null, args)

    //ES6 写法
    f(...args)

    //用 Math.max 求数组中最大的数
    //ES5 写法
    Math.max.apply(null, [2, 33, 3])

    //ES6 写法
    Math.max(...[2, 33, 3])

    //用 push 将一个数组添加到另一个数组尾部
    var arr1 = [0, 1, 2]
    var arr2 = [3, 4, 5]

    //ES5 写法
    Array.prototype.push.apply(arr1, arr2)

    //ES6 写法
    arr1.push(...arr2)
  • 合并数组

    1
    2
    3
    4
    5
    6
    7
    8
    9
    var arr1 = ["a"]
    var arr2 = ["b", "c"]
    var arr3 = ["d"]

    //ES5 写法
    arr1.concat(arr2, arr3)

    //ES6 写法
    ;[...arr1, ...arr2, ...arr3]
  • 与解构赋值结合

    Read more »

旧 React 简易实现

react-old.js
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
import { updateDomProperties } from "./dom-utils.js"

// 根实例
let rootInstance = null
const TEXT_ELEMENT = "TEXT_ELEMENT"

// 创建 VDOM 元素
function createElement(type, config, ...args) {
const props = Object.assign({}, config)
const hasChildren = args.length > 0
const rawChildren = hasChildren ? [].concat(...args) : []

props.children = rawChildren
.filter((c) => c !== null && c !== false)
.map((c) => (c instanceof Object ? c : createTextElement(c)))

return { type, props }
}

function createTextElement(text) {
return createElement(TEXT_ELEMENT, { nodeValue: text })
}

function render(element, container) {
const prevInstance = rootInstance
const nextInstance = reconcile(container, prevInstance, element)
rootInstance = nextInstance
}

// 递归更新子元素
function reconcile(parentDom, instance, element) {
if (instance === null) {
// 创建新实例
const newInstance = instantiate(element)
parentDom.appendChild(newInstance.dom)
return newInstance
} else if (element === null) {
// 删除实例
parentDom.removeChild(instance.dom)
return null
} else if (instance.element.type !== element.type) {
// 如果类型不同,则替换实例
const newInstance = instantiate(element)
// 替换实例
parentDom.replaceChild(newInstance.dom, instance.dom)
return newInstance
} else if (typeof element.type === "string") {
// 更新 DOM 实例
updateDomProperties(instance.dom, instance.element.props, element.props)

// 更新 instance
instance.childInstances = reconcilerChildren(instance, element)
instance.element = element

return instance
} else {
// 更新组件实例
instance.publicInstance.props = element.props
const childElement = instance.publicInstance.render()
const oldChildInstance = instance.childInstance
const childInstance = reconcile(parentDom, oldChildInstance, childElement)

instance.dom = childInstance.dom
instance.childInstance = childInstance
instance.element = element

return instance
}
}

function reconcilerChildren(instance, element) {
const dom = instance.dom
const childInstances = instance.childInstances
const nextChildElements = element.props.children || []
const newChildInstances = []

const count = Math.max(childInstances.length, nextChildElements.length)

// 本 demo, 顺序不同也算作更新

for (let i = 0; i < count; i++) {
const childInstance = childInstances[i]
const childElement = nextChildElements[i]

const newChildInstance = reconcile(dom, childInstance, childElement)

newChildInstances.push(newChildInstance)
}

return newChildInstances.filter((instance) => instance !== null)
}

// 把元素实例化成真实的DOM节点
function instantiate(element) {
const { type, props } = element
const isDomElement = typeof type === "string"

if (isDomElement) {
// 创建 DOM 元素
const isTextElement = type === TEXT_ELEMENT
const dom = isTextElement
? document.createTextNode("")
: document.createElement(type)

// 更新 dom
updateDomProperties(dom, [], props)

// 实例化子元素
const childElements = props.children || []
const childInstances = childElements.map(instantiate)
const childDoms = childInstances.map((childInstance) => childInstance.dom)
childDoms.forEach((childDom) => dom.appendChild(childDom))

const instance = { dom, element, childInstances }

return instance
} else {
// 初始化组件
const instance = {}
const publicInstance = createPublicInstance(element, instance)
const childElement = publicInstance.render() // 拿到 vdom
const childInstance = instantiate(childElement) // 实例化
const dom = childInstance.dom

Object.assign(instance, { dom, element, publicInstance, childInstance })

return instance
}
}

function createPublicInstance(element, internalInstance) {
const { type, props } = element

// type 此时是一个 Class
const publicInstance = new type(props)

publicInstance.__internalInstance = internalInstance

return publicInstance
}

function updateInstance(internalInstance) {
const parentDom = internalInstance.dom.parentNode
const element = internalInstance.element

reconcile(parentDom, internalInstance, element)
}

class Component {
constructor(props) {
this.props = props
this.state = this.state || {}
}

setState(partialState) {
this.state = Object.assign({}, this.state, partialState)
updateInstance(this.__internalInstance)
}

// render 出来的也是 VDOM
render() {}
}

export default { render, createElement, Component }
Read more »

某日被书中一段代码误导

1
2
3
4
5
6
7
8
9
10
11
var promise = new Promise(function (resolve, reject) {
resolve("ok")
setTimeout(function () {
throw new Error("test")
}, 0)
})
promise.then(function (value) {
console.log(value)
})
//ok
//Uncaught Error : test

由于前面还有这样一段话

如果 Promise 状态已经变成 Resolved,再抛出错误是无效的。

当时看到这,思索了许久,为什么已经 resolve 了这个 ERROR 还是可以往外抛出呢?
后面发现,settimeout 是一个异步函数,throw 会在下一轮事件循环开始时抛出,所以无论是否 resolve,这个 ERROR 都是会抛出的。

出兵了!普京指示俄军方确保顿巴斯地区和平,表示“乌是俄历史上不可分割的一部分”!

当地时间 21 日,俄罗斯总统普京在宣布承认顿涅茨克人民共和国和卢甘斯克人民共和国独立后,指示俄罗斯国防部在俄罗斯与顿涅茨克人民共和国和卢甘斯克人民共和国的友好合作互助条约被批准之前,确保俄罗斯武装部队维护顿涅茨克人民共和国和卢甘斯克人民共和国的和平。

据澎湃新闻,当地时间 2 月 21 日,俄罗斯总统普京发表全国电视讲话时表示,乌克兰不仅是邻国还是俄罗斯历史上不可分割的一部分,乌民众是俄方的同志和亲人,是有血缘关系的人。

据悉,联合国安理会将应乌克兰方面请求,于美东时间 21 日晚 9 时(北京时间 22 日上午 10 时)召开紧急会议。本月联合国安理会轮值主席为俄罗斯。

乌克兰地区局势紧张,国际资本市场避险情绪升温,推动股票等权益类资产进一步被抛售,而金价和黄金股均进一步上涨。

继欧洲股市普跌之后,亚太股市也普遍下跌,日经 225 指数开盘跌 1.5%,韩国 Kospi 指数下跌 1.41%。A 股市场今天上午也进一步调整,各大指数均现显著下挫,近 4000 股下跌。港股方面亦在调整,恒生指数盘中大跌超过 3%,截至午盘仍跌 2.95%。

普京要求俄军

维护两个“共和国”的和平

据央视新闻,俄罗斯法律门户网站发布了俄总统普京 21 日签署的承认顿涅茨克人民共和国和卢甘斯克人民共和国的总统令内容。根据总统令,因乌克兰拒绝执行明斯克协议,根据当地人民的意愿,俄罗斯承认两个共和国为独立主权国家。总统令责成俄外交部开始与两国进行建立外交关系的谈判,与俄罗斯其他有关部门起草友好合作互助条约,并按程序完成条约的签署。总统令要求俄罗斯国防部在友好互助条约被批准之前确保俄罗斯武装部队维护顿涅茨克人民共和国和卢甘斯克人民共和国的和平。

当日稍早时,俄罗斯总统普京发表全国视频讲话,宣布承认乌东民间武装自称的顿涅茨克人民共和国和卢甘斯克人民共和国为独立国家。

据环球网援引俄罗斯《观点报》22 日报道称,网上有消息称俄军已开始抵达顿巴斯地区,也有人公布了相关视频。

报道称,国际文传电讯社援引目击者的话说,两个装甲车队已处于“顿涅茨克共和国”并向该其北部和西部前进。

报道还称,乌克兰 OstroV 通讯社援引社交媒体的消息称,“俄军第一批部队正进入”顿巴斯地区。

据央视新闻,俄罗斯国家杜马议员米哈伊尔·谢列梅特当地时间 22 日表示,对于俄罗斯宣布承认乌克兰东部“顿涅茨克人民共和国”与“卢甘斯克人民共和国”独立,西方国家准备对俄罗斯实施新的制裁措施,对此俄罗斯已经做好了一切准备迎接事态发展,俄罗斯不会胆怯。俄罗斯不惧怕西方国家的制裁,我们重视的是人民的生命安全而不是经济。