廖亚军的个人博客

Logo

苟日新,日日新,又日新

Object.keys() / Object.values() / Object.entries()

场景 代码 说明
获取所有键 Object.keys({a:1,b:2}) // ["a","b"] 返回字符串数组
获取所有值 Object.values({a:1,b:2}) // [1,2] 返回值数组
获取键值对 Object.entries({a:1,b:2}) // [[1]] 返回二维数组
对象遍历 Object.entries(obj).forEach(([k,v])=>...) 遍历键值对
注意问题 说明
只返回可枚举属性 继承属性返回不到
键名都是字符串 返回的键数组都是字符串类型
顺序有保证 按对象创建顺序返回

Object.assign()

场景 代码 说明
合并对象 Object.assign({},a,b) // 合并结果 合并多个对象
浅拷贝对象 const copy = Object.assign({}, obj) 复制对象
复制属性 Object.assign(target, src) 将源属性复制到目标
多对象合并 obj1 = Object.assign(obj1, obj2, obj3) 链式合并
注意问题 说明
浅拷贝 不深拷贝嵌套对象
会修改目标 修改目标对象本身
属性覆盖 同名属性后覆盖前

... 对象展开运算符

场景 代码 说明
合并对象 {...a,...b} // 合并结果 合并多个对象
复制对象 {...obj} // 新对象 浅拷贝对象
添加属性 ({...obj, name:"test"}) // 添加name 添加新属性
删除属性 ({...obj, a:undefined, ...{a:undefined}}) 不推荐,用 delete
注意问题 说明
浅拷贝 只拷贝第一层属性
不会修改原对象 返回新对象
后覆盖前 展开顺序决定覆盖关系

Object.create()

场景 代码 说明
继承原型 Object.create(proto) 创建继承对象
继承方法 const child = Object.create(parent) 父级方法被继承
带描述符 Object.create(proto, descriptors) 添加属性描述符
原型链 obj.__proto__ === parent 原型关系设置
注意问题 说明
创建原型链 设置对象的原型
不会创建自身属性 只有继承属性
原型对象 第一个参数是原型对象

对象属性访问

场景 代码 说明
点语法访问 obj.name 简单属性名
方括号访问 obj["name"] 动态属性名
访问特殊名 obj["123abc"] 不能点语法访问
访问符号键 obj[symbol] 符号类型键名
注意问题 说明
点语法限制 特殊字符、数字开头不能用点
方括号支持动态 属性名可以是变量
属性不存在 返回 undefined 不是错误

对象属性定义

场景 代码 说明
定义属性 Object.defineProperty(obj, "key", {value: 1}) 定义单个属性
定义多个 Object.defineProperties(obj, {k1:{value:1},k2:{value:2}}) 定义多个属性
不可写属性 obj.key = value 严格模式下会报错
不可枚举属性 for...in 不遍历不可枚举属性
注意问题 说明
修改配置 配置项影响属性行为
默认配置 定义时设置可写、可枚举、可配置
严格模式 不可写属性设置会抛错

属性检查

场景 代码 说明
检查属性 "name" in obj 检查所有属性(含继承)
检查自身 obj.hasOwnProperty("name") 仅检查自身属性
检查存在 obj.name !== undefined 检查值是否存在
检查枚举 Object.getOwnPropertyDescriptor(obj, "name") 获取属性描述符
注意问题 说明
in 查继承 返回自身和继承属性
hasOwnProperty 查自身 只返回自身属性
undefined 是值 undefined 可能真的是值

Object.fromEntries()

场景 代码 说明
数组转对象 Object.fromEntries([[2]]) 键值对转对象
Map 转对象 Object.fromEntries(new Map()) Map 转对象
表单数据 Object.fromEntries(new FormData()) 表单转对象
反向转换 Object.entries(obj) 对象转键值对
注意问题 说明
较新特性 ES2019 新增
键名转换 键名会自动转字符串
数组格式 必须是 [key, value] 格式

Object.getOwnPropertyNames()

场景 代码 说明
所有属性 Object.getOwnPropertyNames(obj) 自身所有属性名
忽略原型 Object.getOwnPropertyNames(obj) 只获取自身
数组返回 返回属性名数组 包含所有属性
空对象 Object.getOwnPropertyNames({}) 返回空数组
注意问题 说明
不查继承 不返回继承属性
包含符号键 还需 Object.getOwnPropertySymbols()
返回数组 返回字符串数组

Object.getOwnPropertySymbols()

场景 代码 说明
符号属性 Object.getOwnPropertySymbols(obj) 获取符号键属性
内部属性 一些库使用符号键隐藏属性 获取隐藏属性
组合获取 const all = [...Object.getOwnPropertyNames(obj),...Object.getOwnPropertySymbols(obj)] 获取所有键
迭代符号 Reflect.ownKeys(obj) 获取所有自身属性
注意问题 说明
获取符号键 单独获取 Symbol 类型键
隐藏属性 常用于库内部隐藏属性
需要组合 组合使用获取所有键

Reflect.ownKeys()

场景 代码 说明
所有键 Reflect.ownKeys(obj) 获取所有自身键
含符号键 同时包含字符串和符号键 完整键列表
对象操作 用于框架实现属性遍历 框架级操作
组合返回 返回数组 字符串 + 符号
注意问题 说明
ES6 新增 Reflect 对象新增方法
所有键 包含所有类型键名
不可枚举 不可枚举也返回

Object.defineProperty()

场景 代码 说明
定义属性 Object.defineProperty(obj, "name", {value:"test"}) 定义单个属性
描述符 设置 get/set/value/writable/enumerable/configurable 属性描述符
访问器 {get(){...},set(v){...}} 定义访问器属性
只读属性 {writable:false} 创建只读属性
注意问题 说明
严格模式 不可写设置会抛错
配置限制 不可配置后不能再改
getter 设置 get/set 不能和 value/writable 混用

Object.defineProperty() - getter/setter

场景 代码 说明
自定义 getter obj = {get name(){return this._name}} 自定义读取逻辑
自定义 setter obj = {set name(v){this._name=v}} 自定义写入逻辑
数据验证 set age(v){if(v>0)this._age=v} 写入时验证
响应式原理 类似 Vue/React 的响应式 实现响应式系统
注意问题 说明
必须配合 defineProperty 定义器函数必须用此方法
性能影响 getter/setter 可能降低性能
序列化 某些工具不序列化 getter/setter

Object.is()

场景 代码 说明
严格相等 Object.is(1, 1) // true 严格相等判断
相等 NaN Object.is(NaN, NaN) // true NaN 能正确判断
正负零 Object.is(-0, 0) // false 区分正负零
替代 === 替代 === 的不足 更可靠的相等判断
注意问题 说明
替代 === === 更严格
NaN 处理 NaN 能正确识别为相等
特殊值 处理 +0/-0 特殊情况

Object.freeze()

场景 代码 说明
冻结对象 Object.freeze(obj) 冻结对象
不可修改 不能新增/修改/删除属性 只读对象
不可变配置 属性描述符不可改 配置不能修改
不可逆 冻结后不可恢复 单向操作
注意问题 说明
浅冻结 不冻结嵌套对象
深冻结需递归 需递归冻结嵌套对象
严格模式 严格模式下修改会抛错

Object.seal()

场景 代码 说明
密封对象 Object.seal(obj) 密封对象
可修改值 值可以改,但属性不可删 可修改属性值
不可新增 不能新增或删除属性 属性固定
对比冻结 seal 比 freeze 宽松 比 freeze 更灵活
注意问题 说明
可改值 可以修改属性值
不可删增 不能新增或删除属性
可配置 属性仍可配置

Object.preventExtensions()

场景 代码 说明
禁止扩展 Object.preventExtensions(obj) 禁止添加新属性
已删属性 已存在属性可删除 已有属性可操作
可修改 可以修改已有属性 修改已有值
不可逆 一旦禁止无法恢复 单向操作
注意问题 说明
只禁止扩展 不能添加新属性
可删除修改 已有属性可删改
最宽松限制 对象限制中最宽松

Object.hasOwn()

场景 代码 说明
检查属性 Object.hasOwn(obj, "name") ES2022 新增
替代方法 替代 hasOwnProperty 调用 更简洁写法
安全调用 不用担心对象覆盖 不会出错
现代写法 Object.hasOwn(obj,key) 推荐用法
注意问题 说明
较新特性 ES2022 新增
方法调用 直接作为方法调用
不继承 只检查自身属性

对象解构赋值

场景 代码 说明
基础解构 const {name, age} = user 提取属性值
重命名 const {name:n} = user 提取并重命名
默认值 const {name="默认"} = user 提供默认值
嵌套解构 const {user:{name}} = data 嵌套解构
注意问题 说明
属性不存在 返回 undefined
重命名 变量名和属性名可以不同
嵌套限制 嵌套不能太长

对象计算属性名

场景 代码 说明
动态键名 const key = "name"; obj[key] = "test" 动态属性名
表达式键名 obj[{[key]: value}] 对象计算属性名
符号键名 obj[{[symbol]: value}] 符号类型键名
函数键名 obj[{[fn()]: value}] 函数返回值作为键名
注意问题 说明
ES6 新增 计算属性名语法
方括号 使用方括号包裹表达式
键名计算 键名在创建时计算

原型链操作

场景 代码 说明
设置原型 obj.__proto__ = proto 设置对象原型
获取原型 Object.getPrototypeOf(obj) 获取对象原型
检查原型 obj instanceof Constructor 检查原型链
原型链遍历 Object.getPrototypeOf(obj) !== null 遍历原型链
注意问题 说明
不推荐__proto__ 不推荐直接设置 proto
推荐 getPrototypeOf 推荐使用 Object.getPrototypeOf
原型链查找 属性查找遵循原型链

对象方法简写

场景 代码 说明
方法简写 const obj = {add(a,b){return a+b}} 简写方法定义
箭头函数 const obj = {add: (a,b)=>a+b} 箭头函数方法
构造器简写 constructor(){} 简写构造函数
生成器方法 *gen(){yield 1} 简写生成器
注意问题 说明
简写语法 ES6 新增方法简写
函数名 方法名自动设为函数名
原型设置 方法定义在原型上

Object.assign() - 详细

场景 代码 说明
属性拷贝 Object.assign(target, source) 浅拷贝属性
多个源 Object.assign({}, a, b, c) 拷贝多个对象
覆盖规则 后面的覆盖前面的 后覆盖前规则
原型属性 不拷贝原型链 只拷贝自身属性
注意问题 说明
浅拷贝 不深拷贝嵌套对象
修改目标 会修改目标对象
返回目标 返回被修改的目标对象

Object.entries() 和 Map 互转

场景 代码 说明
对象转 Map new Map(Object.entries(obj)) 转 Map 对象
Map 转对象 Object.fromEntries(new Map()) Map 转对象
键值对处理 [...objEntries] 直接迭代键值对
数据转换 在 Map 和对象间转换 数据格式转换
注意问题 说明
键名转字符串 对象键名都是字符串
Map 支持任意 Map 的键可以是任意类型
数据一致 转换后保持数据一致

对象展开与不可变操作

场景 代码 说明
删除属性 const {key, ...rest} = obj 删除某个属性
添加属性 {...obj, key: value} 添加新属性
修改属性 {...obj, key: newValue} 修改属性值
不可变更新 类似 React state 更新 不可变数据更新
注意问题 说明
不可变操作 不修改原对象
浅拷贝 只拷贝第一层
新对象 返回新对象