极简三分钟ES6 - ES8中对象扩展

新增Object.values()和Object.entries()

想象我们管理一个存放水果的仓库(对象)

js 复制代码
const fruitStock = {
  apple: 10,   // 🍎苹果:10箱 
  orange: 15,  // 🍊橙子:15箱
  banana: 8    // 🍌香蕉:8箱 
};

Object.values() :只需清点库存数量(值)

js 复制代码
const stockNumbers = Object.values(fruitStock); 
console.log(stockNumbers);  // [10, 15, 8] → 只关心数量 

Object.entries() :记录完整货品清单(键+值)

js 复制代码
const allRecords = Object.entries(fruitStock); 
console.log(allRecords);  
// [ ["apple", 10], ["orange", 15], ["banana", 8] ] → 完整台账 

一些常见的使用场景

快速提取值集合(Object.values

js 复制代码
// 计算水果总库存 
const total = Object.values(fruitStock).reduce((sum,  num) => sum + num, 0);
console.log(total);  // 33

对象转 Map(Object.entries

js 复制代码
const fruitMap = new Map(Object.entries(fruitStock)); 
console.log(fruitMap.get("orange"));  // 15 → 转为 Map 后查询 

过滤对象属性

js 复制代码
// 找出库存 > 10 的水果
const highStock = Object.entries(fruitStock) 
  .filter(([fruit, count]) => count > 10)
  .map(([fruit]) => fruit);
 
console.log(highStock);  // ["orange"]

替代 for...in 循环

js 复制代码
// 更安全地遍历对象(避免原型污染)
Object.entries(fruitStock).forEach(([fruit,  count]) => {
  console.log(`${fruit}:  ${count}箱`);
});

对象深拷贝技巧

js 复制代码
const copy = Object.fromEntries(Object.entries(fruitStock)); 
console.log(copy);  // {apple:10, orange:15, banana:8} → 全新对象

特殊情况

非对象参数自动转对象

js 复制代码
Object.values("abc");  // ["a", "b", "c"](字符串转包装对象)
Object.entries(42);    // [](数字无属性,返回空数组)

Symbol 属性会被忽略

js 复制代码
const obj = { [Symbol("id")]: 100, name: "test" };
Object.values(obj);    // ["test"] → 跳过 Symbol 
Object.entries(obj);   // [["name", "test"]] 

原型链属性不包含

js 复制代码
function Fruit() { this.type  = "food"; }
Fruit.prototype.color  = "red";
 
const apple = new Fruit();
Object.values(apple);  // ["food"] → 不包含原型属性 

与ES5方案对比

操作需求 ES5 方案 ES8 方案 优势
获取所有值 Object.keys(obj).map(k => obj[k]) Object.values(obj) 代码减少 60%
获取键值对 手动 for...in 循环 Object.entries(obj) 避免原型链污染风险
对象转二维数组 无直接方法 Object.entries(obj) 一行代码完成

选择哪个方法

  • 如下情况使用 Object.values()

    • 统计值总和/平均值
    • 检查值是否满足条件
    • 仅需值集合的场景
  • 如下情况使用 Object.entries()

    • 需同时访问键和值
    • 对象转 Map 或其他数据结构
    • 重构对象属性

Object.getOwnPropertyDescriptors()

对象的"体检报告单"

想象我们要检查一台手机的完整配置

  • 传统方法Object.getOwnPropertyDescriptor() ):只能查单个部件(如摄像头参数)
  • Object.getOwnPropertyDescriptors() :直接生成整机完整参数表(镜头+芯片+屏幕...)
js 复制代码
const phone = {
  brand: "Pixel",
  price: 699,
  get discount() { return this.price  * 0.9 } // getter 计算属性 
};
 
// 获取手机完整配置表
const fullReport = Object.getOwnPropertyDescriptors(phone); 

解决两大痛点

完整复制对象(含 getter/setter)

js 复制代码
const deepCopy = Object.defineProperties( 
  {}, 
  Object.getOwnPropertyDescriptors(phone)  // 保留所有特性
);
deepCopy.price  = 800;
console.log(deepCopy.discount);  // 720(getter 动态计算值)

继承原型方法时不污染目标对象

js 复制代码
// 安全混合对象(不覆盖原型链)
const securityPhone = Object.create( 
  cameraPrototype, // 继承相机功能
  Object.getOwnPropertyDescriptors(phone)  // 添加自有属性 
);

对比其他属性查询方法

方法 作用范围 能否获取 getter/setter 返回结构
Object.keys() 自身可枚举属性 属性名数组
Object.getOwnPropertyNames() 所有自身属性 属性名数组
Object.getOwnPropertyDescriptor() 单个属性 单个描述符对象
Object.getOwnPropertyDescriptors() 所有自身属性 描述符对象集合

一些常见的使用场景

深度克隆对象(保留特性)

js 复制代码
function trueClone(obj) {
  return Object.defineProperties( 
    {}, 
    Object.getOwnPropertyDescriptors(obj) 
  );
}

精确控制类继承

js 复制代码
class PremiumPhone extends Phone {
  constructor() {
    super();
    // 添加会员专属属性(带 getter)
    Object.defineProperties( 
      this, 
      Object.getOwnPropertyDescriptors({ 
        get vipDiscount() { return this.price  * 0.7 }
      })
    );
  }
}

修复 JSON 序列化缺陷

js 复制代码
// JSON.stringify  会忽略 getter!
const phoneJSON = JSON.stringify(phone);  // {brand:"Pixel",price:699}
 
// 通过描述符重建对象 
const restoredPhone = Object.defineProperties( 
  {}, 
  Object.getOwnPropertyDescriptors(phone) 
);

创建不可变对象

js 复制代码
// 锁定所有属性 
const sealedPhone = Object.defineProperties( 
  {}, 
  Object.entries(Object.getOwnPropertyDescriptors(phone)).map(([key,  desc]) => {
    return [key, {...desc, writable: false}] // 全部设为不可写
  })
);
相关推荐
iDao技术魔方9 分钟前
深入Vue 3响应式系统:为什么嵌套对象修改后界面不更新?
javascript·vue.js·ecmascript
历程里程碑13 分钟前
普通数组-----除了自身以外数组的乘积
大数据·javascript·python·算法·elasticsearch·搜索引擎·flask
摸鱼的春哥14 分钟前
春哥的Agent通关秘籍07:5分钟实现文件归类助手【实战】
前端·javascript·后端
念念不忘 必有回响17 分钟前
viepress:vue组件展示和源码功能
前端·javascript·vue.js
Amumu1213821 分钟前
Vue3 Composition API(一)
开发语言·javascript·ecmascript
C澒22 分钟前
多场景多角色前端架构方案:基于页面协议化与模块标准化的通用能力沉淀
前端·架构·系统架构·前端框架
崔庆才丨静觅24 分钟前
稳定好用的 ADSL 拨号代理,就这家了!
前端
江湖有缘25 分钟前
Docker部署music-tag-web音乐标签编辑器
前端·docker·编辑器
hzb6666627 分钟前
unictf2026
开发语言·javascript·安全·web安全·php
恋猫de小郭2 小时前
Flutter Zero 是什么?它的出现有什么意义?为什么你需要了解下?
android·前端·flutter