Vue.js 前置知识:ES6+ 核心特性完全指南

文章目录

    • 一、对象遍历新方式:Object.keys()
      • [1.1 传统方式:for...in](#1.1 传统方式:for...in)
      • [1.2 现代方式:Object.keys() + 数组方法](#1.2 现代方式:Object.keys() + 数组方法)
      • [1.3 实战:按条件过滤后遍历](#1.3 实战:按条件过滤后遍历)
    • 二、展开运算符:拷贝与合并的利器
      • [2.1 核心概念:引用 vs 拷贝](#2.1 核心概念:引用 vs 拷贝)
      • [2.2 拷贝数组与对象](#2.2 拷贝数组与对象)
      • [2.3 合并数组与对象](#2.3 合并数组与对象)
      • [2.4 浅拷贝注意事项](#2.4 浅拷贝注意事项)
    • [三、JSON 序列化与反序列化](#三、JSON 序列化与反序列化)
      • [3.1 普通对象 vs JSON 格式](#3.1 普通对象 vs JSON 格式)
      • [3.2 序列化:JSON.stringify()](#3.2 序列化:JSON.stringify())
      • [3.3 反序列化:JSON.parse()](#3.3 反序列化:JSON.parse())
    • [四、Web 存储:localStorage 与 sessionStorage](#四、Web 存储:localStorage 与 sessionStorage)
      • [4.1 为什么需要 Web 存储?](#4.1 为什么需要 Web 存储?)
      • [4.2 两大存储机制对比](#4.2 两大存储机制对比)
      • [4.3 基本使用](#4.3 基本使用)
      • [4.4 适用场景](#4.4 适用场景)
    • 五、Promise:告别回调地狱
      • [5.1 问题起源:回调地狱](#5.1 问题起源:回调地狱)
      • [5.2 同步 vs 异步](#5.2 同步 vs 异步)
      • [5.3 Promise 基础用法](#5.3 Promise 基础用法)
      • [5.4 链式调用:消灭回调地狱](#5.4 链式调用:消灭回调地狱)
    • 六、Async/Await:异步编程的终极方案
      • [6.1 从 Promise 到 Async/Await](#6.1 从 Promise 到 Async/Await)
      • [6.2 Async/Await 三条核心规则](#6.2 Async/Await 三条核心规则)
      • [6.3 Async/Await 错误处理](#6.3 Async/Await 错误处理)
    • [七、ES Module:模块化导入导出](#七、ES Module:模块化导入导出)
      • [7.1 按需导出与导入(Named Export)](#7.1 按需导出与导入(Named Export))
      • [7.2 默认导出与导入(Default Export)](#7.2 默认导出与导入(Default Export))
      • [7.3 默认导出与按需导出对比](#7.3 默认导出与按需导出对比)
      • [7.4 混合使用](#7.4 混合使用)
    • 全文总结
    • 核心知识点复盘
    • 常见问题与避坑指南

学习 Vue 之前,这些 JavaScript 现代特性你必须先掌握 ------ 从对象遍历到异步编程,一篇文章系统梳理。


一、对象遍历新方式:Object.keys()

1.1 传统方式:for...in

过去遍历一个对象,只能使用 for...in 循环:

js 复制代码
const obj = {
  id: 100001,
  name: 'Bit',
  age: 9,
  address: '陕西省西安市高新区沣惠南路34号'
}

// 传统方式:for-in 遍历对象
for (let key in obj) {
  console.log(key, obj[key])
}

这种方式虽然能用,但存在两个问题:

  • 会遍历原型链上的属性for...in 不仅遍历自身属性,还会遍历继承来的可枚举属性,需要用 hasOwnProperty 过滤。
  • 无法利用数组方法:遍历过程中无法对 key 做过滤、映射等操作,灵活性差。

1.2 现代方式:Object.keys() + 数组方法

Object.keys() 返回对象自身可枚举属性 组成的数组,拿到数组后我们就可以使用 forEachfiltermap 等数组方法,灵活性大幅提升:

js 复制代码
const obj = {
  id: 100001,
  name: 'Bit',
  age: 9,
  address: '陕西省西安市高新区沣惠南路34号'
}

// Object.keys() 返回的是数组:['id', 'name', 'age', 'address']
Object.keys(obj).forEach((key) => {
  console.log(key, obj[key])
})

核心思路Object.keys() 把对象的 key 变成了数组,数组具备丰富的链式操作方法,让对象遍历从"只能傻傻遍历"升级为"可以灵活加工后再遍历"。

1.3 实战:按条件过滤后遍历

假设有一个需求:只遍历对象中以字母 a 开头的属性

js 复制代码
const obj = {
  id: 100001,
  name: 'Bit',
  age: 9,
  address: '陕西省西安市高新区沣惠南路34号'
}

// 链式调用:先过滤,再遍历
Object
  .keys(obj)                              // ['id', 'name', 'age', 'address']
  .filter((key) => key.startsWith('a'))   // ['age', 'address']
  .forEach(key => {
    console.log(key, obj[key])            // age 9, address ...
  })

代码思路解析

步骤 方法 结果
① 获取 key 数组 Object.keys(obj) ['id', 'name', 'age', 'address']
② 过滤以 a 开头 .filter(...) ['age', 'address']
③ 遍历输出 .forEach(...) 输出对应 value

面试重点Object.keys()Object.values()Object.entries() 三者对比 ------ keys 返回键数组,values 返回值数组,entries 返回键值对二维数组。它们都只返回自身可枚举属性,不会拿到原型链上的属性。


二、展开运算符:拷贝与合并的利器

展开运算符 ... 是 ES6 中最常用的语法之一,核心功能就两个:拷贝合并

2.1 核心概念:引用 vs 拷贝

在讲展开运算符之前,必须先理解一个关键区分:

js 复制代码
const arr1 = [11, 22, 33]

// ❌ 这是"引用",不是"拷贝"------两者指向同一块内存,会相互影响
const arr2 = arr1
arr2.push(44)
console.log(arr1)  // [11, 22, 33, 44] → arr1 也被改了!

// ✅ 这才是"拷贝"------值一样,但地址不同,彼此独立
const arr3 = [...arr1]
arr3.push(55)
console.log(arr1)  // [11, 22, 33, 44] → arr1 不受影响

底层原理 :JavaScript 中,对象和数组是引用类型 。直接赋值 arr2 = arr1 只是把内存地址复制了一份,两个变量指向同一个数据。展开运算符 ... 创建的是浅拷贝,会开辟新内存存放数据,新旧数据互不影响。

2.2 拷贝数组与对象

js 复制代码
// 拷贝数组
const arr1 = [11, 22, 33]
const arr2 = [...arr1]   // 展开 arr1 的所有元素,包进新数组
arr2.push(44)
console.log(arr1)         // [11, 22, 33] ------ 原数组不变

// 拷贝对象
const obj1 = {
  id: 10001,
  name: 'Bit',
  age: 9
}
const obj2 = {
  ...obj1                 // 展开 obj1 的所有属性,包进新对象
}
obj2.age = 10
console.log(obj1)         // { id: 10001, name: 'Bit', age: 9 } ------ 原对象不变

2.3 合并数组与对象

合并是展开运算符的另一个高频使用场景:

js 复制代码
// 合并数组
const arr1 = [1, 2, 3]
const arr2 = [4, 5, 6]
const arr = [...arr1, ...arr2]   // 两个数组的元素平铺进新数组
console.log(arr)                  // [1, 2, 3, 4, 5, 6]

// 合并对象
const obj1 = {
  name: 'Jack',
  height: 176
}

const obj2 = {
  height: 180,    // 注意:此属性与 obj1 重名
  age: 18
}

const obj = {
  ...obj1,
  ...obj2         // 同名属性,后面的会覆盖前面的
}
console.log(obj)   // { name: 'Jack', height: 180, age: 18 }

易错点 :合并对象时如果存在同名属性 ,后面展开的会覆盖前面的。这和 Object.assign() 的行为一致,实际开发中常用于合并默认配置和用户配置

2.4 浅拷贝注意事项

展开运算符执行的是浅拷贝(Shallow Copy),只复制一层。如果对象内部还嵌套了对象,内层仍然是引用:

js 复制代码
const obj1 = {
  name: 'Bit',
  info: { phone: '138xxxx' }   // 嵌套对象
}
const obj2 = { ...obj1 }
obj2.info.phone = '139xxxx'    // 修改内层对象
console.log(obj1.info.phone)   // '139xxxx' ------ 内层依然是引用,被影响了!

避坑 :需要完全独立的深拷贝时,可以用 JSON.parse(JSON.stringify(obj))structuredClone(),但要注意前者的局限性(无法处理函数、undefined、循环引用等)。


三、JSON 序列化与反序列化

JSON(JavaScript Object Notation)是前后端数据交互的事实标准。掌握序列化和反序列化是每个前端工程师的基本功。

3.1 普通对象 vs JSON 格式

js 复制代码
// 普通 JavaScript 对象 ------ 属性名可以不加引号
const obj = {
  id: 10001,
  name: 'Bit',
  age: 9
}

// JSON 格式 ------ 属性名必须用双引号包裹(这是规范,不是可选项)
// {
//   "id": 10001,
//   "name": "Bit",
//   "age": 9
// }

两者的核心区别:

对比维度 JavaScript 对象 JSON
属性名引号 可以不写(标识符规则) 必须双引号
值类型 任意 JS 类型 仅 String/Number/Boolean/Array/Object/null
函数 可以包含 ❌ 不支持
undefined 可以包含 ❌ 不支持
用途 程序内使用 数据传输与存储

3.2 序列化:JSON.stringify()

把 JavaScript 对象转为 JSON 字符串,用于发送给后端或存入存储:

js 复制代码
const obj = {
  id: 10001,
  name: 'Bit',
  age: 9
}

// 序列化 → JSON 字符串
console.log(JSON.stringify(obj))
// 输出:'{"id":10001,"name":"Bit","age":9}'

3.3 反序列化:JSON.parse()

把 JSON 字符串还原为 JavaScript 对象,用于解析后端返回的数据:

js 复制代码
const jsonStr = '{"id": 10001, "name": "Bit", "age": 9}'

// 反序列化 → JavaScript 对象
console.log(JSON.parse(jsonStr))
// 输出:{ id: 10001, name: 'Bit', age: 9 }

面试重点JSON.parse() 遇到不合法的 JSON 字符串会抛出异常 ,实际开发中务必用 try...catch 包裹,防止程序崩溃。


四、Web 存储:localStorage 与 sessionStorage

4.1 为什么需要 Web 存储?

浏览器端的存储需求无处不在:用户登录状态、表单草稿、主题偏好、购物车数据......Web Storage API 提供了比 Cookie 更现代、更便捷的客户端存储方案。

4.2 两大存储机制对比

特性 localStorage sessionStorage
生命周期 永久存储,除非手动删除 会话级别,关闭标签页即清除
存储容量 约 5MB 约 5MB
作用域 同源所有标签页共享 仅当前标签页
与服务器通信 不自动发送 不自动发送
API 相同(setItem/getItem/removeItem 相同

4.3 基本使用

js 复制代码
// ========== 存储数据 ==========
// localStorage 和 sessionStorage 的 API 完全一致

// 存 ------ 值必须是字符串
localStorage.setItem('token', 'abc123')
localStorage.setItem('theme', 'dark')

// 存对象需要先序列化
const userInfo = { id: 10001, name: 'Bit', age: 9 }
localStorage.setItem('user', JSON.stringify(userInfo))

// ========== 读取数据 ==========
const token = localStorage.getItem('token')       // 'abc123'
const theme = localStorage.getItem('theme')       // 'dark'

// 取对象需要反序列化
const userStr = localStorage.getItem('user')
const user = JSON.parse(userStr)                  // { id: 10001, name: 'Bit', age: 9 }

// ========== 删除数据 ==========
localStorage.removeItem('token')                   // 删除单个
localStorage.clear()                               // 清空全部

关键步骤 :存储对象时必须 JSON.stringify(),取出时用 JSON.parse() 还原。忘记序列化会导致对象被存为 "[object Object]" 字符串,这是高频踩坑点。

4.4 适用场景

  • localStorage:记住登录状态、用户偏好设置、主题选择、草稿箱等需要长期保留的数据。
  • sessionStorage:表单多步骤填写时的临时数据、页面刷新恢复状态等仅当前会话需要的数据。

五、Promise:告别回调地狱

异步编程是 JavaScript 的核心特性之一。从回调函数到 Promise,再到 async/await,这是前端开发者必须跨越的认知阶梯。

5.1 问题起源:回调地狱

先看一个经典需求:延迟 2 秒输出 1,再延迟 1 秒输出 2,再延迟 1 秒输出 3

js 复制代码
// ❌ 回调地狱 ------ 层层嵌套,难以阅读和维护
setTimeout(() => {
  console.log(1)
  setTimeout(() => {
    console.log(2)
    setTimeout(() => {
      console.log(3)
    }, 1000)
  }, 1000)
}, 2000)

这就是回调地狱(Callback Hell):多个异步操作需要按顺序执行时,回调函数层层嵌套,代码呈倒金字塔形状,可读性极差。

5.2 同步 vs 异步

在深入 Promise 之前,先厘清两个核心概念:

  • 同步代码:串行执行,前面的代码执行完毕,后面的才会开始。会阻塞后续代码。
  • 异步代码:不会阻塞后续代码执行,异步操作在后台运行,完成后通过回调通知结果。
js 复制代码
// 同步示例
console.log('A')
console.log('B')  // 一定在 A 之后输出

// 异步示例
console.log('A')
setTimeout(() => console.log('B'), 1000)  // B 在 1 秒后才输出
console.log('C')                          // C 不会等 B,会立刻输出
// 输出顺序:A → C → B

5.3 Promise 基础用法

Promise 是一个容器,包裹着未来才会完成(或失败)的异步操作:

js 复制代码
// 创建一个 Promise 实例
const p = new Promise((resolve, reject) => {
  // 在这里包装异步代码:定时器、Ajax 请求等
  // 成功 → 调用 resolve(成功的数据)
  // 失败 → 调用 reject(失败的原因)

  setTimeout(() => {
    // resolve('ok')     // 模拟成功
    reject('error')      // 模拟失败
  }, 2000)
})

// 消费 Promise
p.then(
  (msg) => {
    console.log('成功了', msg)     // resolve 走这里
  },
  (err) => {
    console.log('失败了', err)     // reject 走这里
  }
)

Promise 三种状态pending(进行中)→ fulfilled(已成功)→ rejected(已失败)。状态一旦改变就不可逆转,这是 Promise 的核心特性。

5.4 链式调用:消灭回调地狱

Promise 的真正威力在于链式调用 ------ 每个 .then() 都可以返回一个新的 Promise,让异步任务像同步代码一样从上往下写:

js 复制代码
/**
 * 封装延迟输出函数
 * @param {number} duration 延迟的毫秒数
 * @param {*}      n        延迟后输出的值
 * @returns {Promise} 返回 Promise 实例
 */
function delay(duration, n) {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(n)           // 延迟结束后,将 n 作为成功结果传递出去
    }, duration)
  })
}

// 链式调用:扁平化写法,彻底消灭嵌套
delay(2000, 1)
  .then((n1) => {
    console.log(n1)        // 2秒后输出 1
    return delay(1000, 2)  // 返回新的 Promise,交给下一个 then
  })
  .then((n2) => {
    console.log(n2)        // 再过1秒后输出 2
    return delay(1000, 3)  // 继续返回 Promise
  })
  .then((n3) => {
    console.log(n3)        // 再过1秒后输出 3
  })

关键步骤解析

  1. delay(2000, 1) 返回一个 Promise,2 秒后 resolve 出 1
  2. 第一个 .then() 拿到 n1(值为 1),输出后 return 一个新的 Promise
  3. 第二个 .then() 等待这个新 Promise resolve 后拿到 n2,依此类推。
  4. 每个 .then() 中都 return 一个 Promise,这是链式调用得以串联的关键。

核心思路:把异步操作的"嵌套"变成了"平铺",代码从上到下线性阅读,逻辑一目了然。这就是 Promise 解决回调地狱的本质。


六、Async/Await:异步编程的终极方案

Async/Await 是 Promise 的语法糖,它让异步代码写起来像同步代码,可读性达到最优。

6.1 从 Promise 到 Async/Await

还是同一个需求,对比三种写法的差异:

js 复制代码
// 封装延迟输出函数(和上一节相同)
function delay(duration, n) {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(n)
    }, duration)
  })
}

// ========== 写法对比 ==========

// ① 回调地狱 ------ 嵌套地狱
setTimeout(() => {
  console.log(1)
  setTimeout(() => {
    console.log(2)
    setTimeout(() => console.log(3), 1000)
  }, 1000)
}, 2000)

// ② Promise 链式调用 ------ 扁平但仍有 .then 链
delay(2000, 1)
  .then(n1 => { console.log(n1); return delay(1000, 2) })
  .then(n2 => { console.log(n2); return delay(1000, 3) })
  .then(n3 => { console.log(n3) })

// ③ Async/Await ------ 像写同步代码一样写异步 ✅ 最优解
async function log() {
  const n1 = await delay(2000, 1)
  console.log(n1)

  const n2 = await delay(1000, 2)
  console.log(n2)

  const n3 = await delay(1000, 3)
  console.log(n3)
}

log()

6.2 Async/Await 三条核心规则

这是理解 Async/Await 最关键的三个知识点:

  1. await 放在 Promise 实例前 ,它的返回值就是 Promise 的 resolve 参数值。
  2. await 所在函数必须用 async 修饰,否则语法报错。
  3. await 后面的代码会等待 ,也就是前面的 await 执行完毕了,才会执行后续的 await------让异步代码按同步方式串行执行。

6.3 Async/Await 错误处理

js 复制代码
async function fetchData() {
  try {
    const n1 = await delay(2000, 1)
    console.log(n1)
    // 如果某个 await 的 Promise 被 reject,会抛出异常
  } catch (err) {
    console.log('出错了:', err)
  }
}

面试重点async 函数本身返回的是一个 Promiseawait 只能在 async 函数内部使用(ES2022 之后在模块顶层也可以使用 top-level await)。


七、ES Module:模块化导入导出

模块化是工程化的基石。Vue 项目中的 import / export 语法,来自 ES6 官方模块化标准。

7.1 按需导出与导入(Named Export)

一个模块可以有多个按需导出:

js 复制代码
// ========== math.js ------ 定义并导出 ==========

// 定义求和函数并按需导出
export function add(x, y) {
  return x + y
}

// 定义求差函数并按需导出
export function sub(x, y) {
  return x - y
}

// ========== 其他文件中导入 ==========

// 按需导入 ------ 变量名必须与导出时一致,用花括号包裹
import { add, sub } from './utils/math.js'

console.log(add(33, 18))  // 51
console.log(sub(33, 18))  // 15

易错点 :按需导入的变量名必须和导出时的名字完全一致 ,并且用花括号 {} 包起来。

7.2 默认导出与导入(Default Export)

每个模块最多只有一个默认导出:

js 复制代码
// ========== min.js ------ 默认导出 ==========

// 定义求最小值的函数并默认导出
export default function min(m, n) {
  return m > n ? n : m
}

// 注意:export default 在一个模块中最多出现一次!

// ========== 使用方导入 ==========

// 默认导入 ------ 变量名可以自定义,但建议与模块功能保持一致
import min from './utils/min.js'

console.log(min(12, 45))  // 12

7.3 默认导出与按需导出对比

对比维度 默认导出 export default 按需导出 export
每个模块数量 最多 1 个 可以有多个
导入时变量名 可以自定义 必须和导出时一致
导入语法 import xxx from import { xxx } from
典型场景 模块主体功能(如一个 Vue 组件) 工具函数集合(如多个辅助函数)

7.4 混合使用

一个模块可以同时包含默认导出和按需导出:

js 复制代码
// utils.js
export default function main() { /* ... */ }   // 默认导出
export function helper1() { /* ... */ }         // 按需导出
export function helper2() { /* ... */ }         // 按需导出

// 导入时
import main, { helper1, helper2 } from './utils.js'

全文总结

本文系统梳理了学习 Vue.js 之前必须掌握的 7 个 ES6+ 核心特性 ,按照"先概念 → 再原理 → 再实战"的逻辑层层递进:

  1. Object.keys() 将对象 key 转为数组,结合数组方法实现灵活遍历;
  2. 展开运算符 ... 实现数组/对象的浅拷贝与合并,理解引用 vs 拷贝的本质区别;
  3. JSON 序列化/反序列化 是前后端数据交互的桥梁,JSON.stringify()JSON.parse() 必须熟练;
  4. Web 存储(localStorage / sessionStorage)提供浏览器端持久化能力,配合 JSON 实现对象存取;
  5. Promise 解决回调地狱,通过链式调用将异步嵌套变为扁平化代码;
  6. Async/Await 在 Promise 基础上进一步简化,让异步代码写起来像同步代码;
  7. ES Module 模块化系统,是 Vue 组件化开发的基础语法。

这些知识点不是孤立的,它们在实际开发中环环相扣------你用 import 引入模块,用 async/await 发请求,用 JSON.parse 解析数据,用展开运算符合并配置,用 Object.keys 处理数据遍历。掌握它们,学习 Vue 的开发体验会顺畅很多。


核心知识点复盘

序号 知识点 核心要点 一句话总结
1 Object.keys() 返回自身可枚举属性名数组 把对象 key 变数组,解锁数组方法链
2 展开运算符 浅拷贝 + 合并 ... 展开内容,包进新容器
3 JSON.stringify/parse 序列化/反序列化 对象 ↔ 字符串互转,前后端数据桥梁
4 Web Storage setItem/getItem/removeItem 存对象需序列化,取对象需反序列化
5 Promise pending → fulfilled/rejected 包裹异步操作,链式调用消除嵌套
6 Async/Await async 函数 + await Promise Promise 语法糖,让异步代码同步写
7 ES Module export/export default + import 按需导入名字必须一致,默认导入可自定义

常见问题与避坑指南

❓ Q1:Object.keys() 和 for...in 到底有什么区别?

Object.keys() 只返回自身可枚举属性 ,不会遍历原型链;for...in 会遍历原型链上的可枚举属性,需要用 hasOwnProperty 过滤。实际开发中优先用 Object.keys()

❓ Q2:展开运算符是深拷贝还是浅拷贝?

浅拷贝 。只复制第一层,内层嵌套对象仍是引用。需要深拷贝时,可以用 JSON.parse(JSON.stringify(obj))structuredClone(),但要注意前者的局限性(无法处理 functionundefinedDate、循环引用等)。

❓ Q3:localStorage 存对象为什么是 "object Object"?

:因为 localStorage.setItem() 的值必须是字符串,直接存对象会调用 .toString(),结果就是 "[object Object]"。正确做法是先用 JSON.stringify() 序列化后再存,取出时用 JSON.parse() 还原。

❓ Q4:Promise 的 .then() 中 return 和不 return 有什么区别?

return 一个 Promise(或普通值)会传递给下一个 .then(),形成链式传递;不 return 则下一个 .then() 收到的值是 undefined。链式调用的关键在于每个 .then() 必须 return 数据。

❓ Q5:async/await 报错怎么处理?

:用 try...catch 包裹 await 调用。如果 Promise 被 reject,异常会被 catch 捕获。另外,async 函数本身返回 Promise,也可以在调用方用 .catch() 处理。

❓ Q6:按需导入能不能给变量起别名?

:可以,使用 import { add as sum } from './math.js' 语法。这样 add 函数就能以 sum 的名字在当前文件中使用。但默认导入不需要别名语法,直接改名字即可。

❓ Q7:这些前置知识和 Vue 有什么关系?

  • Vue 组件用 export default 导出,用 import 引入。
  • Vue 的 data()methods 返回对象,经常用到展开运算符合并。
  • 调用后端 API 用 axios/fetch,请求响应处理依赖 Promise 和 async/await。
  • 数据格式化、配置合并、对象遍历贯穿 Vue 开发的日常编码。

📝 本文基于 Vue.js 前置知识体系整理,适合 Vue 初学者系统学习 ES6+ 核心特性,也可作为复习参考。

相关推荐
kyriewen17 小时前
别再写useMemo了——2026年这5个React性能优化已经是反模式
前端·react.js·ai编程
OpenTiny社区17 小时前
TinyRobot v0.5.0 新版本强在哪?
前端·vue.js·github
奇牙coding17 小时前
gpt-5.6-sol 接入指南:reasoning_effort 参数配置、推理链验证与常见报错排查
前端·css·gpt·ai
雪隐18 小时前
个人电脑玩AI-10让5060 Ti给你打工——我让 Claude Code 喝上了本地杂粮:Ternary-Bonsai-27B 部署历险记
前端·人工智能·后端
Bigger18 小时前
我受够了每天问“今天吃什么”,于是做了个 AI 菜单工具
前端·人工智能·agent
邢行行19 小时前
记一次 Three.js 踩坑:小球渲染出现诡异黑斑?原因竟然是这样...
前端
颜进强19 小时前
Claude Code -21 Agent 规划化编写范式
前端·后端
夕夕木各19 小时前
Ant Design 本地构建一直卡在 Bundling?一次 UtooPack 排查记录
前端·ant design
人间凡尔赛19 小时前
世界模型入门实战:从RTFM到理解物理世界 | 2026深度技术解析
javascript·人工智能·深度学习·机器学习