Live Note

Remain optimistic

在 TypeScript 的类型系统中,逆变(Contravariance)协变(Covariance)双变(Bivariance)不变(Invariance) 是描述类型兼容性和子类型关系的重要概念。这些术语来源于类型理论,主要用于处理函数类型、泛型和接口的赋值规则。理解这些概念不仅能帮助我们编写更安全的代码,还能让我们更好地设计类型系统。本文将逐一讲解这四种变型,辅以代码示例,让你轻松掌握它们的含义与应用。

Read more »

Node.js is built on Google’s V8 engine, and V8’s garbage collection mechanism is one of its core performance features. In this article, we’ll explore the three primary garbage collection algorithms used in V8: Mark-Sweep, Mark-Compact, and Scavenge, along with their working principles and application scenarios.

V8’s Memory Partition Model

Before diving into garbage collection algorithms, we need to understand V8’s memory partition model. V8 divides memory into two main regions:

Young Generation

  • Contains objects with short lifespans.
  • Typically small in size (e.g., a few MB).
  • Uses the Scavenge algorithm for garbage collection.

Old Generation

  • Contains objects with longer lifespans.
  • Typically larger in size (e.g., hundreds of MB).
  • Uses the Mark-Sweep and Mark-Compact algorithms for garbage collection.
Read more »

Vite 为什么快?

Vite 的速度优势主要来源于其基于原生 ESM(ES Modules)的开发模式和高效的构建过程

原生 ESM 的开发服务器

传统打包工具(如 Webpack)的问题

  • Webpack 在开发模式下会将所有模块打包成一个或多个 bundle 文件,即使只修改了一个文件,也需要重新打包整个 bundle。
  • 这种打包过程涉及大量的文件读取、解析、转换和写入操作,随着项目规模增加,启动时间和热更新时间会显著变慢。

Vite 的解决方案

  • Vite 利用现代浏览器对 原生 ES Modules(ESM) 的支持,在开发模式下不进行打包,而是直接通过 HTTP 请求按需加载模块。
  • 浏览器支持 <script type="module">,可以动态加载 ESM 模块,Vite 的开发服务器将源码直接以 ESM 格式提供给浏览器。
  • 启动速度快:
    • Vite 的开发服务器启动时,只需要初始化一个简单的 HTTP 服务器,无需预先打包整个项目。
    • 文件按需加载,只有访问到的模块才会被处理(例如解析和转换),大大减少了初始启动时间。
  • 按需编译:
    • Vite 使用 Esbuild(一个极快的 JavaScript/TS 编译器)对 TypeScript、JSX 等非标准 ESM 文件进行预编译,生成浏览器可识别的 ESM 格式。
    • Esbuild 的性能比传统工具(如 Babel)快 10-100 倍,因为它是基于 Go 语言实现的,充分利用了多核 CPU。
Read more »

原理

通过改写[].__proto__上的方法,实现对Array原生方法的拦截。

源码位置为 /core/instance/observer/array.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
// cache the original Array.prototype
const originalPrototype = Array.prototype

// create an object from original Array.prototype
const arrayMethods = Object.create(originalPrototype)

const methodsToPatch = [
"push",
"pop",
"shift",
"unshift",
"splice",
"sort",
"reverse",
]

methodsToPatch.forEach((method) => {
arrayMethods[method] = function (...args) {
// use original Array methods to get the result
const result = originalPrototype[method].apply(this, args)

// proxy here
console.log(`catch ${method}`)

return result
}
})

const a = [1, 2, 3]
a.__proto__ = arrayMethods

a.push(1)
a.reverse()
a.pop()

console.log(a)

:class 绑定

1
2
3
4
5
6
7
8
9
10
11
12
13
<div id="app">
<h1 :class="['italic', 'red', {'active': flag}]">Test H1 Message</h1>
<h1 :class="classObj">Test H1 Message</h1>
</div>
<script>
var vm = new Vue({
el: "#app",
data: {
flag: true,
classObj: { red: true, thin: true, italic: true, active: false },
},
})
</script>
Read more »