极简三分钟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}] // 全部设为不可写
  })
);
相关推荐
代码的余温2 小时前
Web服务器VS应用服务器:核心差异解析
运维·服务器·前端
一涯2 小时前
日常小常识记录
前端
那一抹阳光多灿烂2 小时前
CSS 编码规范
前端·css
degree5202 小时前
CSS :has() 选择器详解:为什么它是“父选择器”?如何实现真正的容器查询?
前端·css·css3
૮・ﻌ・2 小时前
CSS高级技巧---精灵图、字体图标、布局技巧
前端·css
昔人'2 小时前
纯`css`固定标题并在滚动时为其添加动画
前端·css
超人不会飛2 小时前
Vue markdown组件 | 流式 | 大模型应用
前端·javascript·github
小白64023 小时前
前端梳理体系从常问问题去完善-基础篇(html,css,js,ts)
前端·css·html
怪可爱的地球人3 小时前
vue3小白入门
前端