头图
🧑🏫 作者:全栈老李
📅 更新时间:2025 年 05 月
🧑💻 适合人群:前端初学者、进阶开发者
🚀 版权:本文由全栈老李原创,转载请注明出处。

大家好,我是全栈老李。今天咱们聊聊ES6中Object的那些新方法——它们就像瑞士军刀,让对象操作变得前所未有的顺手。想象一下,以前你要手动遍历对象属性时那笨拙的样子,现在有了这些方法,简直像开了挂。

一、Object.assign:对象的"复制粘贴"

Object.assign是ES6中最常用的对象方法之一,它的作用就像把多个对象的属性"复制粘贴"到目标对象上。

// 全栈老李示例:Object.assign基础用法
const target = { a: 1 };
const source1 = { b: 2 };
const source2 = { c: 3 };

const result = Object.assign(target, source1, source2);
console.log(result); // { a: 1, b: 2, c: 3 }
console.log(target); // { a: 1, b: 2, c: 3 } —— 注意target也被修改了!

这里有个坑要注意:Object.assign会直接修改第一个参数对象本身!如果你想保留原对象,可以这样:

// 全栈老李提醒:安全的浅拷贝方式
const newObj = Object.assign({}, target, source1, source2);

使用场景

  • 合并配置对象(比如合并默认配置和用户自定义配置)
  • 创建对象的浅拷贝
  • 给对象添加多个属性

不过要注意,它只能做浅拷贝。如果属性值是对象,拷贝的是引用:

const obj = { a: { b: 1 } };
const copy = Object.assign({}, obj);
copy.a.b = 2;
console.log(obj.a.b); // 2 —— 原对象也被改了!

二、Object.keys/values/entries:对象的"解剖工具"

这三个方法让遍历对象变得异常简单,它们分别返回对象的键、值、键值对数组。

// 全栈老李示例:对象遍历三件套
const person = {
  name: '老李',
  age: 35,
  job: '全栈工程师'
};

console.log(Object.keys(person));    // ["name", "age", "job"]
console.log(Object.values(person));  // ["老李", 35, "全栈工程师"]
console.log(Object.entries(person)); // [["name", "老李"], ["age", 35], ["job", "全栈工程师"]]

使用场景

  • 将对象转换为Map:new Map(Object.entries(obj))
  • 表单验证时检查是否有空值
  • 配合数组方法进行链式操作

比如统计对象属性值的类型:

// 全栈老李的实用技巧
const typeCount = Object.values(person)
  .map(value => typeof value)
  .reduce((acc, type) => {
    acc[type] = (acc[type] || 0) + 1;
    return acc;
  }, {});

console.log(typeCount); // { string: 2, number: 1 }

三、Object.fromEntries:数组变对象的"魔法"

这是ES2019新增的方法,可以看作是Object.entries的逆操作:

// 全栈老李示例:键值对数组转对象
const entries = [
  ['name', '全栈老李'],
  ['age', 35],
  ['skills', ['JS', 'Node', 'React']]
];

const obj = Object.fromEntries(entries);
console.log(obj);
// {
//   name: "全栈老李",
//   age: 35,
//   skills: ["JS", "Node", "React"]
// }

使用场景

  • 将URL查询参数转换为对象
  • 处理Map结构转换为普通对象
  • 配合Object.entries实现对象转换管道

比如处理URL参数:

// 全栈老李实战:解析URL参数
const paramsString = 'name=全栈老李&age=35&skill=JS';
const searchParams = new URLSearchParams(paramsString);

console.log(Object.fromEntries(searchParams));
// { name: "全栈老李", age: "35", skill: "JS" }

四、Object.is:比===更严格的相等判断

你可能觉得===已经够严格了,但Object.is在某些边界情况下更精确:

// 全栈老李的对比实验
console.log(+0 === -0);          // true
console.log(Object.is(+0, -0));  // false

console.log(NaN === NaN);        // false
console.log(Object.is(NaN, NaN)); // true

使用场景

  • 需要精确比较+0和-0的场景
  • 需要识别NaN的场景
  • 实现不可变数据结构的比较

五、Object.getOwnPropertyDescriptors:属性的"完整档案"

这个方法可以获取对象属性的完整描述符(包括value、writable、enumerable、configurable等):

// 全栈老李示例:属性描述符查看
const obj = {
  name: '全栈老李',
  get age() {
    return 35;
  }
};

console.log(Object.getOwnPropertyDescriptors(obj));
// {
//   name: {
//     value: "全栈老李",
//     writable: true,
//     enumerable: true,
//     configurable: true
//   },
//   age: {
//     get: [Function: get age],
//     set: undefined,
//     enumerable: true,
//     configurable: true
//   }
// }

使用场景

  • 精确复制对象(包括getter/setter)
  • 创建具有相同属性特性的新对象
  • 高级属性操作和元编程

六、实战应用:实现一个深拷贝函数

结合几个方法,我们可以实现一个简单的深拷贝:

// 全栈老李的深拷贝实现(基础版)
function deepClone(obj) {
  if (obj === null || typeof obj !== 'object') {
    return obj;
  }
  
  if (obj instanceof Date) {
    return new Date(obj);
  }
  
  if (obj instanceof RegExp) {
    return new RegExp(obj);
  }
  
  const descriptors = Object.getOwnPropertyDescriptors(obj);
  const clone = Object.create(
    Object.getPrototypeOf(obj),
    descriptors
  );
  
  Object.entries(descriptors).forEach(([key, descriptor]) => {
    if (descriptor.value && typeof descriptor.value === 'object') {
      clone[key] = deepClone(descriptor.value);
    }
  });
  
  return clone;
}

const original = { 
  name: '全栈老李', 
  meta: { 
    skills: ['JS', 'Node'], 
    createdAt: new Date() 
  } 
};
const cloned = deepClone(original);

console.log(cloned.meta === original.meta); // false —— 深拷贝成功!

课后作业:面试题挑战

题目

const obj1 = { a: 1, b: 2 };
const obj2 = { b: 3, c: 4 };
const obj3 = { c: 5, d: 6 };

const result = Object.assign({}, obj1, obj2, obj3);
console.log(result);

请问console.log输出什么?在评论区留下你的答案,我会随机抽几位同学的答案进行点评哦~

(提示:注意属性的覆盖顺序和Object.assign的特性)


我是全栈老李,一个资深Coder!

写码不易,如果你觉得有用,点赞 + 收藏 + 关注 走一波!感谢鼓励!🌹🌹🌹


全栈老李
1 声望0 粉丝