粉粉蕉的笔记本粉粉蕉的笔记本
  • JAVA

    • 代码笔记
    • Java8实战
    • 分布式事务实战(Seata)
    • 模板引擎(FreeMarker)
    • SpringSecurity
    • Maven
  • PYTHON

    • 概述
    • python3
    • python3(菜鸟教程)
    • pandas
    • numpy
    • matplotlib
  • 中间件

    • Kafka
    • RocketMQ
    • Redis
    • MongoDB
    • Elastic Search
  • 数据库

    • Mysql
  • 前端

    • HTML
    • CSS
    • Javascript
    • Vue学习笔记
  • 设计模式
  • 大数据

    • 概览
    • Hadoop
    • Hive
  • 机器学习

    • 机器学习概览
  • openclaw实战笔记
  • claudecode实战笔记
  • linux命令速查
  • windows命令速查
  • Docker笔记
  • kubernetes学习笔记
  • kubernetes实操笔记
  • 运维工具大全
  • git操作宝典
  • 概率论
  • 线性代数
  • 统计学
  • 金融知识学习
  • 聚宽
  • 因子分析
  • 后端

    • JAVA基础
    • JAVA多线程
    • JVM
    • 分布式相关
    • 数据库
  • 前端

    • HTML
    • CSS
    • JAVASCRIPT
    • VUE3
    • 网络
    • 前端工程化
    • nodejs
  • 健身

    • 笔记
    • 训练计划
  • 读书笔记

    • 《深度学习》
  • 其他

    • RSS
    • 资源导航
    • 医保
    • 装修攻略
我也想搭建这样的博客!
🚋开往
  • JAVA

    • 代码笔记
    • Java8实战
    • 分布式事务实战(Seata)
    • 模板引擎(FreeMarker)
    • SpringSecurity
    • Maven
  • PYTHON

    • 概述
    • python3
    • python3(菜鸟教程)
    • pandas
    • numpy
    • matplotlib
  • 中间件

    • Kafka
    • RocketMQ
    • Redis
    • MongoDB
    • Elastic Search
  • 数据库

    • Mysql
  • 前端

    • HTML
    • CSS
    • Javascript
    • Vue学习笔记
  • 设计模式
  • 大数据

    • 概览
    • Hadoop
    • Hive
  • 机器学习

    • 机器学习概览
  • openclaw实战笔记
  • claudecode实战笔记
  • linux命令速查
  • windows命令速查
  • Docker笔记
  • kubernetes学习笔记
  • kubernetes实操笔记
  • 运维工具大全
  • git操作宝典
  • 概率论
  • 线性代数
  • 统计学
  • 金融知识学习
  • 聚宽
  • 因子分析
  • 后端

    • JAVA基础
    • JAVA多线程
    • JVM
    • 分布式相关
    • 数据库
  • 前端

    • HTML
    • CSS
    • JAVASCRIPT
    • VUE3
    • 网络
    • 前端工程化
    • nodejs
  • 健身

    • 笔记
    • 训练计划
  • 读书笔记

    • 《深度学习》
  • 其他

    • RSS
    • 资源导航
    • 医保
    • 装修攻略
我也想搭建这样的博客!
🚋开往

JavaScript 教程

数组(Array)

创建数组

const arr = [1, 2, 3]
const arr2 = new Array(3).fill(0)    // [0, 0, 0]
const arr3 = Array.from({ length: 3 }, (_, i) => i + 1)  // [1, 2, 3]
const arr4 = Array.from('hello')     // ['h', 'e', 'l', 'l', 'o']

增删元素

const arr = [1, 2, 3]

// 末尾增删
arr.push(4, 5)       // [1, 2, 3, 4, 5],返回新长度
arr.pop()            // [1, 2, 3, 4],返回被删除的元素 5

// 开头增删
arr.unshift(0)       // [0, 1, 2, 3, 4],返回新长度
arr.shift()          // [1, 2, 3, 4],返回被删除的元素 0

// 任意位置增删(splice 会修改原数组)
// splice(起始下标, 删除个数, ...插入元素)
arr.splice(1, 0, 'a', 'b')   // 在下标1处插入,不删除 → [1, 'a', 'b', 2, 3, 4]
arr.splice(1, 2)              // 从下标1开始删除2个   → [1, 2, 3, 4]
arr.splice(1, 1, 'x')         // 替换下标1的元素      → [1, 'x', 3, 4]

查找元素

const arr = [1, 2, 3, 2, 4]

arr.indexOf(2)            // 1,第一次出现的下标,找不到返回 -1
arr.lastIndexOf(2)        // 3,最后一次出现的下标
arr.includes(3)           // true,是否包含

// find / findIndex:按条件查找(返回第一个匹配项)
const users = [{ id: 1, name: 'Tom' }, { id: 2, name: 'Jerry' }]
users.find(u => u.id === 2)        // { id: 2, name: 'Jerry' }
users.findIndex(u => u.id === 2)   // 1
users.findLast(u => u.id < 3)      // { id: 2, name: 'Jerry' }(从后往前找)

遍历

const arr = [1, 2, 3]

// forEach:无返回值,纯遍历
arr.forEach((item, index) => {
  console.log(index, item)
})

// for...of:最简洁,支持 break/continue
for (const item of arr) {
  if (item === 2) break
  console.log(item)
}

// 同时获取下标和值
for (const [index, item] of arr.entries()) {
  console.log(index, item)
}

转换(返回新数组,不修改原数组)

const arr = [1, 2, 3, 4, 5]

// map:逐项转换
arr.map(x => x * 2)              // [2, 4, 6, 8, 10]

// filter:过滤
arr.filter(x => x > 2)           // [3, 4, 5]

// reduce:累积计算
arr.reduce((acc, x) => acc + x, 0)         // 15(求和)
arr.reduce((acc, x) => acc * x, 1)         // 120(求积)

// 常用 reduce 场景:数组转对象
const users = [{ id: 1, name: 'Tom' }, { id: 2, name: 'Jerry' }]
const userMap = users.reduce((acc, u) => {
  acc[u.id] = u
  return acc
}, {})
// { 1: { id: 1, name: 'Tom' }, 2: { id: 2, name: 'Jerry' } }

// flat:展平嵌套数组
[1, [2, [3, [4]]]].flat()     // [1, 2, [3, [4]]],默认展平一层
[1, [2, [3, [4]]]].flat(2)    // [1, 2, 3, [4]],展平两层
[1, [2, [3, [4]]]].flat(Infinity)  // [1, 2, 3, 4],全部展平

// flatMap:map + flat(1) 的组合
['hello world', 'foo bar'].flatMap(s => s.split(' '))
// ['hello', 'world', 'foo', 'bar']

排序

const arr = [3, 1, 4, 1, 5, 9]

// sort 默认按 Unicode 排序(数字会有问题!)
[10, 9, 2].sort()             // ❌ [10, 2, 9],字符串排序

// 数字升序
arr.sort((a, b) => a - b)     // [1, 1, 3, 4, 5, 9]

// 数字降序
arr.sort((a, b) => b - a)     // [9, 5, 4, 3, 1, 1]

// 对象数组按字段排序
const users = [{ name: 'Tom', age: 25 }, { name: 'Anna', age: 20 }]
users.sort((a, b) => a.age - b.age)          // 按年龄升序
users.sort((a, b) => a.name.localeCompare(b.name))  // 按姓名字母序

// toSorted:不修改原数组(ES2023)
const sorted = arr.toSorted((a, b) => a - b)

截取与合并

const arr = [1, 2, 3, 4, 5]

// slice:截取片段(不修改原数组)
arr.slice(1, 3)     // [2, 3],含头不含尾
arr.slice(-2)       // [4, 5],负数从末尾算
arr.slice()         // [1, 2, 3, 4, 5],浅拷贝整个数组

// concat:合并数组(不修改原数组)
[1, 2].concat([3, 4], [5])   // [1, 2, 3, 4, 5]

// 展开运算符合并(更常用)
const merged = [...arr, ...arr2]

判断与统计

const arr = [1, 2, 3, 4, 5]

arr.every(x => x > 0)    // true,是否全部满足条件
arr.some(x => x > 4)     // true,是否有至少一个满足条件
arr.length               // 5,数组长度

Array.isArray(arr)       // true,判断是否为数组
Array.isArray('hello')   // false

其他常用操作

const arr = [1, 2, 3]

// join:数组转字符串
arr.join('-')            // '1-2-3'
arr.join('')             // '123'

// reverse:反转(修改原数组)
arr.reverse()            // [3, 2, 1]
arr.toReversed()         // 返回新数组,不修改原数组(ES2023)

// fill:填充
new Array(5).fill(0)         // [0, 0, 0, 0, 0]
arr.fill(0, 1, 3)            // 将下标 1~2 填为 0

// 数组去重(配合 Set)
const unique = [...new Set([1, 2, 2, 3, 3])]   // [1, 2, 3]

// 数组解构
const [first, second, ...rest] = [1, 2, 3, 4, 5]
// first=1, second=2, rest=[3,4,5]

Map

Map 是键值对集合,与普通对象的区别:键可以是任意类型(对象、函数、NaN 等),且保证插入顺序。

创建与基本操作

// 创建空 Map
const map = new Map()

// 从数组初始化
const map2 = new Map([
  ['name', 'Tom'],
  ['age', 25],
  [{ id: 1 }, 'object key'],  // 键可以是对象
])

// 增 / 改(链式调用)
map.set('name', 'Tom')
   .set('age', 25)
   .set(true, 'boolean key')

// 查
map.get('name')       // 'Tom'
map.get('notExist')   // undefined

// 是否存在
map.has('name')       // true
map.has('email')      // false

// 删
map.delete('age')     // true,成功删除返回 true

// 清空
map.clear()

// 大小
map.size              // 数量(注意不是 .length)

遍历

const map = new Map([['a', 1], ['b', 2], ['c', 3]])

// forEach
map.forEach((value, key) => {
  console.log(key, value)   // 注意:回调参数顺序是 value, key
})

// for...of(推荐)
for (const [key, value] of map) {
  console.log(key, value)
}

// 只遍历键 / 只遍历值
for (const key of map.keys()) { ... }
for (const value of map.values()) { ... }

// 转为数组
const entries = [...map]          // [['a',1], ['b',2], ['c',3]]
const keys = [...map.keys()]      // ['a', 'b', 'c']
const values = [...map.values()]  // [1, 2, 3]

Map 与对象互转

const obj = { name: 'Tom', age: 25 }

// 对象 → Map
const map = new Map(Object.entries(obj))

// Map → 对象(键必须是字符串/Symbol)
const obj2 = Object.fromEntries(map)
// { name: 'Tom', age: 25 }

适用场景

// ① 用对象作为键(普通对象做不到)
const cache = new Map()
const domEl = document.querySelector('#app')
cache.set(domEl, { clicks: 0 })

// ② 需要频繁增删键值对(比对象性能更好)
const registry = new Map()
registry.set('handler1', fn1)
registry.delete('handler1')

// ③ 需要知道键值对数量
console.log(registry.size)   // 比 Object.keys(obj).length 更直接

// ④ 统计词频
const words = ['apple', 'banana', 'apple', 'cherry', 'banana', 'apple']
const freq = new Map()
for (const word of words) {
  freq.set(word, (freq.get(word) ?? 0) + 1)
}
// Map { 'apple' => 3, 'banana' => 2, 'cherry' => 1 }

Set

Set 是值的集合,自动去重,保证每个值只出现一次。

创建与基本操作

// 创建空 Set
const set = new Set()

// 从数组初始化(自动去重)
const set2 = new Set([1, 2, 2, 3, 3, 3])
// Set { 1, 2, 3 }

// 增
set.add(1).add(2).add(3).add(2)  // 链式,重复值被忽略
// Set { 1, 2, 3 }

// 是否存在
set.has(1)    // true
set.has(99)   // false

// 删
set.delete(2)   // true
set.clear()     // 清空

// 大小
set.size        // 数量

遍历

const set = new Set(['a', 'b', 'c'])

// for...of(推荐)
for (const item of set) {
  console.log(item)
}

// forEach
set.forEach(item => console.log(item))

// 转数组
const arr = [...set]           // ['a', 'b', 'c']
const arr2 = Array.from(set)   // ['a', 'b', 'c']

集合运算

const a = new Set([1, 2, 3, 4])
const b = new Set([3, 4, 5, 6])

// 并集
const union = new Set([...a, ...b])
// Set { 1, 2, 3, 4, 5, 6 }

// 交集
const intersection = new Set([...a].filter(x => b.has(x)))
// Set { 3, 4 }

// 差集(a 有但 b 没有)
const difference = new Set([...a].filter(x => !b.has(x)))
// Set { 1, 2 }

// 子集判断(b 是否是 a 的子集)
const isSubset = [...b].every(x => a.has(x))   // false

适用场景

// ① 数组去重(最常用)
const arr = [1, 2, 2, 3, 3, 3]
const unique = [...new Set(arr)]   // [1, 2, 3]

// ② 快速判断某值是否在集合中(比数组 includes 性能好)
const allowedRoles = new Set(['admin', 'editor', 'viewer'])
if (allowedRoles.has(userRole)) { /* 有权限 */ }

// ③ 统计不重复数量
const visitors = ['user1', 'user2', 'user1', 'user3']
const uniqueCount = new Set(visitors).size   // 3

// ④ 标签/权限去重合并
const tagsA = ['vue', 'js', 'css']
const tagsB = ['js', 'ts', 'vue']
const allTags = [...new Set([...tagsA, ...tagsB])]
// ['vue', 'js', 'css', 'ts']

Map、Set、Object、Array 对比

ObjectArrayMapSet
键/索引类型字符串/Symbol数字任意类型—
值重复键不可重复可重复键不可重复值不可重复
有序不保证有序插入有序插入有序
大小获取Object.keys().length.length.size.size
适用场景结构化数据(JSON)有序列表任意键的映射去重/集合运算

模块(Module)

命名导出与导入

一个文件可以有多个命名导出,导入时名称必须对应。

// utils/math.js —— 命名导出
export const PI = 3.14159

export function add(a, b) {
  return a + b
}

export function multiply(a, b) {
  return a * b
}
// main.js —— 命名导入
import { add, multiply } from './utils/math.js'

add(1, 2)        // 3
multiply(3, 4)   // 12

// 导入时重命名(as)
import { add as sum } from './utils/math.js'
sum(1, 2)        // 3

// 导入全部(命名空间导入)
import * as Math from './utils/math.js'
Math.add(1, 2)
Math.PI          // 3.14159

默认导出与导入

一个文件只能有一个默认导出,导入时可以使用任意名称。

// utils/request.js —— 默认导出
const request = {
  get(url) { /* ... */ },
  post(url, data) { /* ... */ },
}

export default request
// main.js —— 默认导入(名称随意)
import request from './utils/request.js'
import myRequest from './utils/request.js'  // 同一模块,名称不同也可以

混合导出(默认 + 命名)

实际项目中最常见的模式:

// api/user.js
import request from '@/utils/request'

// 命名导出:具体的 API 方法
export function getUserInfo(id) {
  return request.get(`/user/${id}`)
}

export function updateUser(id, data) {
  return request.put(`/user/${id}`, data)
}

export function deleteUser(id) {
  return request.delete(`/user/${id}`)
}

// 默认导出:聚合所有方法(可选)
export default { getUserInfo, updateUser, deleteUser }
// 使用时按需导入(Tree-shaking 友好)
import { getUserInfo, updateUser } from '@/api/user'

// 或者导入默认导出
import userApi from '@/api/user'
userApi.getUserInfo(1)

重新导出(聚合导出)

用于将多个模块的导出集中到一个入口文件,方便统一引用。

// api/index.js —— 聚合所有 API 模块
export { getUserInfo, updateUser } from './user'
export { getOrderList, createOrder } from './order'
export { getProductList } from './product'

// 重新导出默认导出
export { default as request } from '@/utils/request'
// 其他文件只需从一个入口引入
import { getUserInfo, getOrderList, getProductList } from '@/api'

动态导入

在运行时按需加载模块,返回 Promise,适合路由懒加载、条件加载等场景。

// 基础用法
const module = await import('./utils/math.js')
module.add(1, 2)

// 解构导入
const { add, multiply } = await import('./utils/math.js')

// 条件加载(根据用户权限加载不同模块)
async function loadAdminModule() {
  if (user.role === 'admin') {
    const { AdminPanel } = await import('./components/AdminPanel.vue')
    return AdminPanel
  }
}

// Vue Router 路由懒加载(最常见的场景)
const routes = [
  {
    path: '/dashboard',
    component: () => import('@/views/DashboardView.vue')
  }
]

在 Vue3 项目中的实际用法

API 层(src/api/):

// src/api/user.js
import request from '@/utils/request'

export const getUserInfo = (id) => request.get(`/user/${id}`)
export const getUserList = (params) => request.get('/user/list', { params })
export const createUser = (data) => request.post('/user', data)
export const updateUser = (id, data) => request.put(`/user/${id}`, data)
export const deleteUser = (id) => request.delete(`/user/${id}`)

工具函数(src/utils/):

// src/utils/format.js
export function formatDate(date, fmt = 'YYYY-MM-DD') { /* ... */ }
export function formatMoney(amount) {
  return `¥${amount.toFixed(2)}`
}
export function formatFileSize(bytes) {
  if (bytes < 1024) return `${bytes}B`
  if (bytes < 1024 ** 2) return `${(bytes / 1024).toFixed(1)}KB`
  return `${(bytes / 1024 ** 2).toFixed(1)}MB`
}

常量(src/constants/):

// src/constants/status.js
export const ORDER_STATUS = {
  PENDING: 0,
  PAID: 1,
  SHIPPED: 2,
  DONE: 3,
  CANCELLED: 4,
}

export const ORDER_STATUS_LABEL = {
  [ORDER_STATUS.PENDING]: '待付款',
  [ORDER_STATUS.PAID]: '已付款',
  [ORDER_STATUS.SHIPPED]: '已发货',
  [ORDER_STATUS.DONE]: '已完成',
  [ORDER_STATUS.CANCELLED]: '已取消',
}

Composable(src/composables/):

// src/composables/useUserList.js
import { ref, reactive, onMounted } from 'vue'
import { getUserList } from '@/api/user'

// 封装可复用的数据逻辑,在任意组件中导入使用
export function useUserList() {
  const list = ref([])
  const loading = ref(false)
  const pagination = reactive({ page: 1, pageSize: 10, total: 0 })

  const loadData = async () => {
    loading.value = true
    try {
      const res = await getUserList({ page: pagination.page, pageSize: pagination.pageSize })
      list.value = res.list
      pagination.total = res.total
    } finally {
      loading.value = false
    }
  }

  onMounted(loadData)

  return { list, loading, pagination, loadData }
}
<!-- 在组件中使用 composable -->
<script setup>
import { useUserList } from '@/composables/useUserList'

const { list, loading, pagination, loadData } = useUserList()
</script>

CommonJS vs ES Module 速查

CommonJS(Node.js 老项目)ES Module(现代标准)
导出module.exports = ...export / export default
导入require('./file')import ... from './file'
动态导入require() 可在任意位置调用import() 函数(返回 Promise)
加载时机运行时同步加载编译时静态分析
Tree-shaking不支持支持
浏览器支持不支持原生支持(现代浏览器)
Last Updated: 6/25/26, 2:37 AM
Contributors: dongyz8