首页
/ JavaScript 对象操作实战指南:从基础到高级技巧

JavaScript 对象操作实战指南:从基础到高级技巧

2025-07-08 07:52:29作者:裘晴惠Vivianne

前言

在 JavaScript 开发中,对象操作是最基础也是最重要的技能之一。本文将深入探讨 JavaScript 对象的各种操作技巧,从简单的键值遍历到复杂的代理模式应用,帮助开发者掌握对象操作的核心技术。

1. 嵌套对象键值遍历

处理嵌套对象时,递归是最常用的方法。下面是一个打印嵌套对象所有键值的函数:

function keyValuePrinter(obj) {
  for (let key in obj) {
    if (typeof obj[key] !== "object") {
      console.log("[" + key + " : " + obj[key] + "]");
    } else {
      keyValuePrinter(obj[key]);
    }
  }
}

技术要点

  • 使用 typeof 检查属性类型
  • 递归处理嵌套对象
  • for...in 循环遍历对象属性

2. 对象清空方法

清空对象有两种常见方式:

// 方法1:删除所有属性
for (let key in obj) {
  if (obj.hasOwnProperty(key)) {
    delete obj[key];
  }
}

// 方法2:创建新对象并继承原型
const newObj = {};
Object.setPrototypeOf(newObj, obj);

注意事项

  • 方法1会保留原型链
  • 方法2创建的是全新对象,只继承原型

3. 深拷贝实现方案

深拷贝是 JavaScript 中的常见需求,以下是几种实现方式:

// 浅拷贝方法
Object.assign({}, obj);
{ ...obj };

// 深拷贝方法
JSON.parse(JSON.stringify(obj));

// 递归深拷贝函数
function deepCopy(obj) {
  if (!obj) return obj;
  const copyObj = {};
  for (const key in obj) {
    if (typeof obj[key] !== "object" || Array.isArray(obj[key]))
      copyObj[key] = obj[key];
    else copyObj[key] = deepCopy(obj[key]);
  }
  return copyObj;
}

注意事项

  • JSON 方法会丢失函数和特殊对象类型
  • 递归方法可以处理复杂嵌套结构

4. 对象属性访问控制

通过 getter 和 setter 可以精确控制对象属性的访问:

// 使用 defineProperty
const obj = { marks: 0 };
Object.defineProperty(obj, "marks", {
  set(value) {
    if (value < 0) throw new Error("Marks cant be less than zero");
    marks = value;
  },
  get() {
    return marks;
  },
});

// 使用 get/set 语法糖
const obj = {
  _marks: 0,
  set marks(value) {
    if (value < 0) throw new Error("Marks cant be less than zero");
    this._marks = value;
  },
  get marks() {
    return this._marks;
  },
};

5. 只读属性实现

创建只能设置一次的属性:

function userObjectCreator(id) {
  const obj = {};
  Object.defineProperty(obj, "userid", {
    value: id,
    writable: false,
  });
  return obj;
}

6. 对象序列化过滤

安全地序列化对象,排除敏感信息:

const obj = {
  id: 1,
  username: "John",
  password: "secret",
  email: "john@email.com",
};

// 方法1:使用替换函数
JSON.stringify(obj, (key, value) => 
  key === "password" ? undefined : value
);

// 方法2:指定属性白名单
JSON.stringify(obj, ["id", "username", "email"]);

7. 迭代器模式实现

创建自定义迭代器:

function makeIterator(array) {
  let nextIndex = 0;
  return {
    next: function() {
      return nextIndex < array.length
        ? { value: array[nextIndex++], done: false }
        : { done: true };
    },
  };
}

8. 方法链式调用

实现流畅接口:

const obj = {
  id: 1,
  displayId() {
    console.log("Id: " + this.id);
    return this;
  },
  displayName() {
    console.log("Name: " + this.username);
    return this;
  }
};

obj.displayId().displayName();

9. 高级对象模式

访问计数器

function counterObject() {
  const symCounter = Symbol("counter");
  return {
    [symCounter]: 0,
    get counter() { return ++this[symCounter]; },
    set counter() { throw new Error("Cannot set counter"); }
  };
}

类数组对象

const arrayLikeObject = {
  length: 0,
  push: function(item) {
    Array.prototype.push.call(this, item);
  },
  pop: function() {
    Array.prototype.pop.call(this);
  }
};

10. 对象深度比较

function deepEqual(obj1, obj2) {
  const keys1 = Object.keys(obj1);
  const keys2 = Object.keys(obj2);
  if (keys1.length !== keys2.length) return false;

  for (const key of keys1) {
    const val1 = obj1[key];
    const val2 = obj2[key];
    const areObjects = typeof val1 === "object" && typeof val2 === "object";
    if ((areObjects && !deepEqual(val1, val2)) || 
        (!areObjects && val1 !== val2)) {
      return false;
    }
  }
  return true;
}

11. 类与面向对象

class Employee {
  constructor(id, name) {
    this.id = id;
    this.name = name;
  }
  
  setSalary(base, variable) {
    this.salary = base + variable;
  }
}

12. 代理高级应用

只读现有属性

const readOnlyObj = new Proxy(obj, {
  set(target, key, value) {
    if (target.hasOwnProperty(key)) {
      throw new Error("Object properties are read-only");
    }
    target[key] = value;
  }
});

范围检查

const range = new Proxy({ start: 10, end: 50 }, {
  has(target, value) {
    return value >= target.start && value <= target.end;
  }
});

25 in range; // true

13. 循环引用处理

检测循环引用

function doesObjectHaveCircularRef(obj) {
  try {
    JSON.stringify(obj);
    return false;
  } catch {
    return true;
  }
}

消除循环引用

function removeCircularRef(obj) {
  const set = new WeakSet([obj]);
  (function iterateObj(obj) {
    for (let key in obj) {
      if (typeof obj[key] === "object") {
        if (set.has(obj[key])) delete obj[key];
        else {
          set.add(obj[key]);
          iterateObj(obj[key]);
        }
      }
    }
  })(obj);
}

14. 动态嵌套属性

function ProxyObject(obj) {
  return new Proxy(obj, {
    get: (target, property) => {
      if (!(property in target)) {
        target[property] = new ProxyObject({});
      }
      return target[property];
    },
  });
}

const obj = new ProxyObject({});
obj.x.y.z = "nested value"; // 自动创建嵌套结构

结语

本文涵盖了 JavaScript 对象操作的各个方面,从基础到高级技巧。掌握这些技术将大大提升你在日常开发中处理复杂对象结构的能力。建议读者在实际项目中尝试应用这些模式,并根据具体需求进行调整和优化。