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双精度浮点存储规则,二进制无法精准表示部分十进制小数。
-
字符串方法会不会修改原数据? 所有字符串方法均为纯函数,不会改动原字符串,返回新字符串。