Skip to content

Commit

Permalink
feat: two post about ts and js
Browse files Browse the repository at this point in the history
  • Loading branch information
minmaxw1024 committed Dec 4, 2024
1 parent 86e49b1 commit 32c924a
Show file tree
Hide file tree
Showing 2 changed files with 394 additions and 0 deletions.
158 changes: 158 additions & 0 deletions posts/ts_and_js_best_practise_01_zh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
---
title: JavaScript 和 TypeScript 最佳实践
published_at: 2024-11-29T15:00:00.000Z
snippet: 这篇文章作者详细介绍了不少 JS 和 TS 中的最佳实践, 非常实用。
---

## JavaScript 和 TypeScript 核心概念

### 4 个基础特性

1. **原始类型(Primitives)**

- 原始类型包括 5 种传统类型:`null``undefined``boolean``number``string`,以及新增的两种类型:`symbol``bigint`
- **重点**
- `symbol` 主要用于创建对象的唯一键,避免键值冲突。
- 类型强制(Coercion):当调用原始类型的函数时,JavaScript 会用其对象包装器(如 `Boolean``Number`)包装原始值,从而实现调用。

2. **函数(Functions)**

- **创建方式**
- 函数声明:`function functionName() {}`
- 箭头函数:`() => {}`
- 对象字面量中的方法:`{ key: function() {} }`
- 类方法:`class MyClass { myMethod() {} }`
- **最佳实践**
- 在顶层使用函数声明以利用提升(Hoisting)。
- 在嵌套函数中使用箭头函数。
- 单参数箭头函数省略括号:`val => val * 2`

3. **对象(Objects)**

- **创建方式**
- 对象字面量:`{ key: value }`
- 使用 `new` 调用构造函数:`new Date()`
- 类实例化:`class MyClass {}`
- **对象字面量**:更适合组织数据和代码,避免使用类的复杂性。
- ****
- 通常避免用类来处理 IO 数据或作为项目结构的核心。
- 适合动态数据和需要封装逻辑的场景,例如数据结构(如 `Map`)。
- **建议**
- 对于 IO 数据,使用接口(`interface`)定义数据结构,使用对象字面量组织相关方法。

4. **类型(Types)**
- **定义方式**
- 类型别名:`type MyType = ...`
- 接口:`interface MyInterface { ... }`
- **使用场景**
- 使用类型别名定义联合类型或简单结构。
- 使用接口定义复杂对象结构。

---

### 脚本(文件)类型

1. **声明型(Declaration)**

- 导出单个声明,例如枚举或类型:`HttpStatusCodes.ts`

2. **模块型(Modular)**

- 导出包含相关函数或变量的对象字面量:`UserRepo.ts`

3. **库存型(Inventory)**

- 存储全局共享的小型声明:`types.ts`

4. **线性型(Linear)**
- 执行一系列命令的文件:`setup-db.ts`

---

### 文件组织结构

- **推荐顺序**

1. 变量(只读或常量)
2. 类型
3. 运行逻辑(可选,保持短小)
4. 函数
5. 类(仅限小型类,大型类应独立文件)

- **注意事项**
- `export default` 始终放在文件末尾。
- 在线性脚本中,代码可按任务分组,而非按类型组织。

---

### 何时使用类?

- **适合场景**

- 动态数据需要与方法紧密耦合。
- 需要封装状态和逻辑,例如数据结构(如 `Map`)。
- 需要依赖注入,确保在多个地方使用同一实例。

- **避免场景**
- 处理 IO 数据:类实例化时方法不会传递,需额外构造或使用静态方法。
- 项目核心架构:使用函数式或过程式编程简化项目,不依赖类的状态管理。

---

### 示例代码

#### 函数声明 vs 箭头函数

```typescript
function declaredFunction() {
console.log("Function declaration");
}

const arrowFunction = (val: number) => val * 2;
```

#### 对象字面量与类

```typescript
// 对象字面量
const user = {
name: "John",
sayHello() {
console.log(`Hello, ${this.name}`);
},
};

//
class User {
constructor(public name: string) {}
sayHello() {
console.log(`Hello, ${this.name}`);
}
}
```

#### 使用接口和模块化脚本管理数据

```typescript
// User.ts
export interface IUser {
name: string;
age: number;
}

const User = {
isValid(user: IUser): boolean {
return !!user.name && user.age > 0;
},
};

export default User;
```

---

### 总结

- **优先使用函数声明和对象字面量**,简化代码结构。
- **避免使用类组织项目或处理 IO 数据**,改用接口和模块化脚本。
- 遵循文件组织规则,确保代码可维护性和清晰性。
236 changes: 236 additions & 0 deletions posts/ts_and_js_best_practise_02_zh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
---
title: JavaScript 和 TypeScript 最佳实践
published_at: 2024-12-02T15:00:00.000Z
snippet: 这篇文章作者详细介绍了不少 JS 和 TS 中的最佳实践, 非常实用。
---

## 命名规则

### 文件/文件夹

1. **文件夹**

- 一般用小写加连字符,例如 `shared-utils/`
- React 中包含组件的文件夹可用首字母大写,例如 `Home/` 包含 `Home.tsx``Home.test.tsx`

2. **文件命名**
- **声明脚本**:文件名应与声明名称匹配,例如导出 `useSetState` 的文件应命名为 `useSetState.ts`
- **模块脚本**:使用 PascalCase,例如 `UserRepo.ts`
- **库存脚本**:使用小写加连字符,例如 `shared-types.ts`
- **线性脚本**:使用小写加连字符,例如 `setup-db.ts`
- **辅助测试文件夹**:以双下划线包裹,例如 `__test-helpers__/`

---

### 变量命名

1. **全局静态变量**

- 用大写加下划线(`UPPER_SNAKE_CASE`),例如:`const SALT_ROUNDS = 12;`
- 简单的数组或对象(没有嵌套)也用 `UPPER_SNAKE_CASE`

2. **局部变量**

- 在函数内部声明的变量使用 `camelCase`
- 布尔变量一般以 `is` 开头,例如:`session.isLoggedIn`

3. **相关变量分组**
- 使用单个声明块定义相关变量,提高代码可读性和性能,但不要过度使用。
```typescript
const FOO_BAR = "abc",
MAX_COUNT = 10;
```

---

### 函数命名

1. **格式**

- 一般使用 `camelCase`
- JSX 组件使用 `PascalCase`
- 函数名应反映动作,使用动词格式,例如 `fetchName()`
- 简单的常量返回函数可省略动词:

```typescript
const Errors = {
SomeError: "Error message",
EmailNotFound(email: string) {
return `User with email "${email}" not found.`;
},
} as const;
```

2. **特殊规则**
- 辅助函数(仅限文件内部使用)用下划线开头,例如:`function _helperFn() {}`
- IO 数据返回用 `fetch`,非 IO 数据返回用 `get`,例如:
- `user.getFullName()`
- `UserRepo.fetchUser()`

---

### 对象命名

1. **不可变对象**

- 全局静态对象使用 `UPPER_SNAKE_CASE`
- 模块或声明脚本导出的对象使用 `PascalCase`,并用 `as const` 标记为不可变。

2. **动态对象**
- 在函数内部的对象用 `camelCase`
- 运行时返回的动态对象也用 `camelCase`

---

### 类和枚举

1. ****

- 类名用 PascalCase。
- 类的静态只读变量用 PascalCase,例如 `Dog.Species`
- 实例变量和方法用 `camelCase`

2. **枚举**
- 枚举名和键均用 PascalCase,例如:
```typescript
enum NodeEnvs {
Dev = "development",
Prod = "production",
}
```

---

### 类型和接口

1. **类型别名**

- 类型名以 `T` 开头,例如:`type TMouseEvent = React.MouseEvent<HtmlButtonElement>;`

2. **接口**
- 接口名以 `I` 开头,例如:`interface IUser { name: string; email: string; }`

---

### 注释规则

1. **函数注释**

- 使用 `/** Comment */` 格式,放在函数声明上方,首字母大写并以句号结束。

```typescript
/**
* Add two numbers.
*/
function add(a: number, b: number): number {
return a + b;
}
```

2. **代码块注释**

- 在函数内部用 `//` 注释,注释首字母大写并以句号结束。

3. **分隔代码块**

-`// **** Section Name **** //` 分隔文件的主要部分(变量、类型、函数等)。

4. **复杂逻辑注释**
- 对复杂逻辑分块注释,用 `/** */` 分隔大的功能。

---

### 导入规则

1. **组织导入**

- 库在顶部,自己代码在下方。
- 相同目录的导入放在最底部。
- 超过字符限制的导入单独换行。

2. **示例**

```typescript
import express from "express";
import { UserRepo } from "@src/repos/UserRepo";
import helpers from "./helpers";
```

---

### 示例脚本

1. **模块脚本**

```typescript
// MailUtil.ts
const SUPPORT_EMAIL = "[email protected]";
/**
* Send an email.
*/
function sendEmail(to: string, subject: string, body: string) {
console.log(`Sending email to ${to}`);
}
export default {
sendEmail,
} as const;
```

2. **声明脚本**

```typescript
// EnvVars.ts
export default {
PORT: process.env.PORT,
DB_HOST: process.env.DB_HOST,
} as const;
```

3. **线性脚本**

```typescript
// server.ts
import express from "express";
const app = express();
app.use(middleware);
export default app;
```

---

### 其他代码风格

1. **布尔表达式**

- 用括号提升可读性:
```typescript
if ((isFoo && isBar) || isBaz) {
console.log("Condition met.");
}
```

2. **可选链**

- 使用 `?.` 替代 `foo && foo.bar`
- 使用 `??` 替代 `(str || '')`

3. **长条件语句**

- 每行一个逻辑条件,嵌套逻辑缩进。
```typescript
if (user?.isActive && (role !== "ADMIN" || permissions?.length > 0)) {
// Do something
}
```

4. **对象参数格式**
- 对象字面量的花括号放在函数参数同一行:
```typescript
doSomething("arg1", { key: "value" }, "arg2");
```

0 comments on commit 32c924a

Please sign in to comment.