JavaScript内置对象与元编程全解|String/Number/Math/Date/Symbol/RegExp/Object/defineProperty/Proxy/Reflect(面试+实战)

多数开发者会用内置对象,但真正拉开差距的是是否理解属性描述符、代理拦截和 Reflect 反射这些底层能力。

JavaScript 提供了大量原生内置对象与API,覆盖基础数据处理、正则、时间、数学运算,以及高阶元编程能力。多数开发者只会简单调用,却不懂底层特性、边界坑点、响应式核心原理。

本文一次性全覆盖你指定的所有核心知识点:Object、defineProperty、String、Number、Math、Date、Symbol、RegExp、Proxy、Reflect。从基础API到Vue2/Vue3底层元编程原理,兼顾业务实战与前端高频面试考点。

一、Object 核心对象(万物原型)

Object 是 JS 所有引用类型的顶层父类,数组、函数、自定义对象均继承自 Object,掌握其静态方法是对象处理的核心。

1.1 常用静态API(生产高频)

  • Object.keys(obj):获取对象自身可枚举属性名,返回数组,不包含原型属性、不可枚举属性

  • Object.values(obj):获取对象自身可枚举属性值,返回数组

  • Object.entries(obj):获取键值对数组,可直接用于 Map 初始化、对象遍历

  • Object.assign(target, source):浅拷贝对象,合并属性,仅拷贝可枚举自身属性

  • Object.freeze(obj):冻结对象,禁止增删改属性、禁止修改原型,浅冻结

  • Object.seal(obj):密封对象,禁止增删属性,允许修改已有属性值

  • Object.is(a, b):精准判断相等,修复 `===` 缺陷(可识别 NaN === NaN、区分 ±0)

1.2 属性描述符前置认知

JS 对象每个属性都自带描述符,控制属性的读写、枚举、配置特性,是 defineProperty、响应式原理 的底层基础。

四大特性:value(属性值)、writable(可写)、enumerable(可枚举)、configurable(可删除/可配置)

二、Object.defineProperty(Vue2 核心原理)

defineProperty是 ES5 推出的属性劫持API,能够监听对象属性的读取与修改,是 Vue2 响应式底层核心,面试必考重点。

2.1 语法结构

Object.defineProperty(obj, prop, descriptor)
  • obj:目标对象

  • prop:需要监听的属性名

  • descriptor:属性描述符(数据描述符 / 存取描述符)

2.2 两种描述符规则(互斥)

数据描述符和存取描述符不能同时使用

1. 数据描述符

value、writable:控制属性值与是否可修改

2. 存取描述符(核心)

get():读取属性时触发;set(val):修改属性时触发

2.3 最简响应式劫持示例

const obj = {}
let value = 10

Object.defineProperty(obj, 'num', {
  enumerable: true,
  configurable: true,
  get() {
    console.log('读取属性')
    return value
  },
  set(newVal) {
    console.log('修改属性', newVal)
    value = newVal
  }
})

obj.num     // 读取属性
obj.num = 20// 修改属性

2.4 致命缺陷(Vue2 痛点)

  • 只能监听已有属性,无法监听新增、删除属性

  • 无法监听数组下标修改、数组长度变更

  • 必须遍历对象所有属性递归劫持,性能开销大

三、Proxy 代理对象(Vue3 核心原理)

Proxy 是 ES6 元编程API,用于拦截、劫持对象的所有操作,弥补 defineProperty 所有缺陷,是 Vue3 响应式底层核心。

3.1 核心特性

不侵入原对象,创建代理对象,拦截:属性读取、修改、删除、新增、遍历、方法调用等13种操作

3.2 基础语法与拦截示例

const target = { name: '前端' }
const handler = {
  // 拦截读取
  get(target, prop) {
    console.log('拦截读取:', prop)
    return target[prop]
  },
  // 拦截修改/新增
  set(target, prop, value) {
    console.log('拦截修改/新增:', prop, value)
    target[prop] = value
    return true
  },
  // 拦截删除
  deleteProperty(target, prop) {
    console.log('拦截删除:', prop)
    delete target[prop]
    return true
  }
}

const proxyObj = new Proxy(target, handler)

3.3 Proxy 优势(对比 defineProperty)

  • 监听新增、删除属性,解决 Vue2 新增属性不响应问题

  • 原生支持数组全部操作(下标、长度、push、splice 等)

  • 无需遍历递归,按需劫持,性能更优

  • 拦截操作更多,支持元编程能力更强

缺点:ES6 新API,无法 polyfill,不兼容IE浏览器

四、Reflect 反射对象

Reflect 是 ES6 配套 Proxy 的标准化反射API,用于替代传统 Object 操作方法,让对象操作更规范、函数化。

4.1 核心作用

  • 统一对象操作语法,将命令式操作改为函数式调用

  • 配合 Proxy 使用,完成原对象默认行为

  • 返回布尔值,精准判断操作是否成功,无报错崩溃风险

4.2 常用API

Reflect.get(target, prop)    // 读取属性
Reflect.set(target, prop, val)// 设置属性
Reflect.has(target, prop)     // 判断属性是否存在
Reflect.deleteProperty(target, prop) // 删除属性
Reflect.ownKeys(target)       // 获取所有属性(包含不可枚举)

4.3 Proxy + Reflect 标准写法(企业规范)

const proxy = new Proxy(obj, {
  get(target, prop) {
    // 执行原生默认读取逻辑
    return Reflect.get(target, prop)
  },
  set(target, prop, val) {
    return Reflect.set(target, prop, val)
  }
})

五、Symbol 原始数据类型

Symbol 是 ES6 新增的第七种原始数据类型,代表唯一、不可重复的值,用于解决对象属性名冲突、定义私有属性、内置标识。

5.1 核心特性

  • 绝对唯一:Symbol() 每次创建都是全新值,永不相等

  • 不可遍历:Symbol 属性不会被 for...in、Object.keys 遍历

  • 隐式转换报错,禁止参与运算

5.2 基础用法

const s1 = Symbol('token')
const s2 = Symbol('token')
console.log(s1 === s2) // false

// 全局注册表(可复用)
const s3 = Symbol.for('key')
const s4 = Symbol.for('key')
console.log(s3 === s4) // true

5.3 实战场景

  • 对象私有属性,防止属性覆盖冲突

  • 定义常量、枚举状态

  • 内置 Symbol 常量(Symbol.iterator 迭代器)

六、String 字符串常用API

字符串是开发最高频操作类型,所有字符串方法均为非变异方法,不会修改原字符串

6.1 查询类

  • indexOf/lastIndexOf:查找索引,不存在返回 -1

  • includes():判断是否包含子串,返回布尔

  • startsWith/endsWith:判断开头/结尾字符

6.2 截取类

  • slice(start, end):支持负数索引,最推荐

  • substring:不支持负数,自动修正索引顺序

  • substr(start, length):按长度截取,已废弃

6.3 转换与格式化

  • toUpperCase/toLowerCase:大小写转换

  • trim/trimStart/trimEnd:去除空格

  • split(sep):字符串转数组,高频用于数据拆分

  • replace/replaceAll:替换字符,支持正则匹配替换

七、Number 数值对象与精度问题

7.1 常用静态API

  • Number.isInteger():判断是否为整数

  • Number.isNaN():精准判断NaN,优于全局isNaN

  • Number.parseFloat/parseInt:数值解析转换

  • Number.MAX_SAFE_INTEGER:最大安全整数 2^53\-1

7.2 核心坑点(面试高频)

JS 数值遵循 IEEE754 双精度浮点数规范,存在浮点精度丢失

0.1 + 0.2 // 0.30000000000000004

解决方案:小数放大整数运算、使用 decimal 库、固定小数 toFixed()

八、Math 数学工具API

Math 是静态工具对象,无需实例化,专注数值运算。

8.1 高频方法

  • Math.max/min:取最大/最小值,配合扩展运算符求数组极值

  • Math.floor/ceil/round:向下取整、向上取整、四舍五入

  • Math.random():生成 [0,1) 随机数

  • Math.abs:绝对值、Math.pow:幂运算、Math.sqrt:开平方

8.2 常用随机整数封装

// 生成 [min, max] 随机整数
function getRandom(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min
}

九、Date 日期对象

Date 用于时间戳与日期格式化,原生API繁琐,是业务高频场景,核心掌握时间戳与格式转换。

9.1 常用创建方式

new Date() // 当前时间
new Date(1700000000000) // 时间戳转日期
new Date('2025-01-01') // 字符串解析

9.2 核心方法

  • getTime():获取毫秒时间戳(最标准)

  • getFullYear/getMonth/getDate:年、月(0-11)、日

  • getHours/getMinutes/getSeconds:时分秒

避坑:getMonth 返回 0-11,需要 +1 展示真实月份

9.3 常用时间格式化封装(业务通用)

function formatDate(time) {
  const d = new Date(time)
  const y = d.getFullYear()
  const m = (d.getMonth() + 1).toString().padStart(2, '0')
  const day = d.getDate().toString().padStart(2, '0')
  return `${y}-${m}-${day}`
}

十、RegExp 正则表达式对象

RegExp 用于字符串匹配、校验、替换,是前端表单校验、数据清洗核心工具。

10.1 创建方式

// 字面量(推荐)
const reg1 = /\d+/g
// 构造函数(动态正则)
const reg2 = new RegExp('\\d+', 'g')

10.2 常用修饰符

  • g:全局匹配

  • i:忽略大小写

  • m:多行匹配

10.3 核心方法

  • test():校验字符串是否匹配,返回布尔(表单校验首选)

  • exec():捕获匹配内容,返回匹配数组

10.4 高频正则场景

手机号、邮箱、密码强度、身份证、空格过滤、特殊字符过滤均依赖 RegExp 实现。

十一、核心原理对比(面试绝杀)

11.1 defineProperty vs Proxy

  • defineProperty:属性级劫持,只能监听已有属性,不支持数组、新增/删除属性,Vue2 采用,兼容IE

  • Proxy:对象级劫持,监听所有操作,支持数组、新增删除属性,Vue3 采用,不兼容IE

11.2 Proxy + Reflect 意义

Proxy 拦截操作,Reflect 还原原生行为,实现拦截增强、逻辑解耦、标准化元编程

十二、全文核心总结(必背考点)

  • Object:提供对象遍历、拷贝、冻结、相等判断能力,是所有引用类型的顶层原型

  • defineProperty:Vue2响应式核心,劫持已有属性读写,存在监听缺陷

  • Proxy/Reflect:Vue3响应式核心,全方位拦截对象操作,弥补 defineProperty 短板

  • Symbol:生成唯一值,解决属性冲突、实现私有属性、不可枚举

  • String:所有方法不修改原串,掌握查询、截取、替换、格式化API

  • Number/Math:处理数值运算,重点规避浮点精度丢失问题

  • Date:时间戳转换、日期格式化,注意月份0起始坑点

  • RegExp:正则匹配校验,test用于布尔判断,exec用于内容捕获

十三、高频面试简答题

  • Object.defineProperty 为什么被 Proxy 替代? 无法监听新增、删除属性和数组变更,需递归遍历,性能差、场景有限。

  • Reflect 的作用是什么? 标准化对象操作,配合Proxy完成原生默认行为,统一返回值、规避报错。

  • Symbol 属性有什么特点? 唯一不重复、不可枚举、可定义私有属性,避免全局属性冲突。

  • JS 小数精度丢失原因? 遵循IEEE754双精度浮点存储规则,二进制无法精准表示部分十进制小数。

  • 字符串方法会不会修改原数据? 所有字符串方法均为纯函数,不会改动原字符串,返回新字符串。

本文总结

  • Object、属性描述符和 defineProperty 是理解 Vue2 响应式与对象可配置性的底层起点。
  • Proxy 加 Reflect 把对象操作统一成可拦截、可回退的标准接口,是现代前端元编程与 Vue3 响应式的核心基础。
  • String、Number、Math、Date、Symbol、RegExp 这些看似基础的对象,恰恰是业务代码里最容易埋下边界 Bug 的地方。
GYSTACK 文章文末广告 硅云云服务器活动 适合个人项目、轻量建站和出海业务部署。
后浪云移动端信息流广告 后浪云主机服务 适合长期部署、独立站和海外机房需求。