Z
ZHANK
数组与对象

对象进阶

掌握 Object.keys/values/entries、属性描述符

对象进阶

深入理解 JavaScript 对象的特性与方法。

学完本章你将: 掌握属性描述符、合并复制、冻结密封。


对象合并与复制

javascript
// Object.assign 浅拷贝
let target = { a: 1 };
let source = { b: 2, c: 3 };
Object.assign(target, source);
console.log(target); // { a: 1, b: 2, c: 3 }

// 浅拷贝到空对象
let obj = { x: 1, y: { z: 2 } };
let copy = Object.assign({}, obj);
copy.y.z = 99;
console.log(obj.y.z);  // 99(嵌套对象被共享!)

// 展开运算符(推荐)
let clone = { ...obj, extra: "new" };
console.log(clone); // { x: 1, y: { z: 99 }, extra: "new" }

深拷贝

javascript
let original = {
    name: "Alice",
    scores: [90, 85],
    address: { city: "北京" },
};

// JSON 方式(有限制)
let deep1 = JSON.parse(JSON.stringify(original));
deep1.address.city = "上海";
console.log(original.address.city); // "北京"(未影响)

// ⚠️ JSON 不能处理:函数、undefined、Symbol、循环引用

// structuredClone(现代推荐)
let deep2 = structuredClone(original);
deep2.scores.push(100);
console.log(original.scores); // [90, 85](未影响)

属性描述符

javascript
let user = {};

Object.defineProperty(user, "name", {
    value: "Alice",
    writable: false,     // 不能修改
    enumerable: true,    // 可被枚举
    configurable: false, // 不能删除/重新定义
});

user.name = "Bob";   // 静默失败(严格模式报错)
console.log(user.name); // "Alice"

// 获取描述符
let desc = Object.getOwnPropertyDescriptor(user, "name");
console.log(desc); // { value: "Alice", writable: false, ... }

冻结与密封

javascript
let obj = { x: 1, y: 2 };

// Object.freeze:完全不可变
let frozen = Object.freeze({ a: 1, nested: { b: 2 } });
// frozen.a = 10; // ❌ 静默失败
frozen.nested.b = 20; // ✅ 浅冻结,嵌套对象仍可修改!

console.log(Object.isFrozen(frozen)); // true

// Object.seal:不能增删属性,但可修改
let sealed = Object.seal({ a: 1 });
sealed.a = 10;       // ✅ 可以修改
// sealed.b = 20;    // ❌ 不能新增
// delete sealed.a;  // ❌ 不能删除

console.log(Object.isSealed(sealed)); // true