You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让JavaScript对象(如ServiceWorkerRegistration)的属性可枚举?

如何让ServiceWorkerRegistration对象的属性变为可枚举?

问题描述

我通过以下代码获取了一个ServiceWorkerRegistration类型的对象:

const reg = await navigator.serviceWorker.register(`https://www.myurl.com/Worker.js`, {scope:"/"});

使用console.log(reg)能看到对象的各类属性,但执行JSON.stringify(reg)返回{},Object.keys(reg)返回[],经查这是因为对象的属性不可枚举。目前只能手动访问单个属性或逐个设置属性为可枚举,我希望能通过Object.keys(reg).forEach遍历属性,请问如何让该对象的属性变为可枚举?

解决方案

方案1:修改原对象属性为可枚举(遍历原型链)

ServiceWorkerRegistration的多数属性定义在原型链上且不可枚举,我们可以递归遍历其原型链,将所有属性的可枚举性设为true:

function makeAllPropertiesEnumerable(obj) {
  let currentObj = obj;
  while (currentObj !== null) {
    const props = Object.getOwnPropertyNames(currentObj);
    props.forEach(prop => {
      const descriptor = Object.getOwnPropertyDescriptor(currentObj, prop);
      if (descriptor && !descriptor.enumerable) {
        descriptor.enumerable = true;
        Object.defineProperty(currentObj, prop, descriptor);
      }
    });
    currentObj = Object.getPrototypeOf(currentObj);
  }
}

// 使用示例
makeAllPropertiesEnumerable(reg);
// 现在可以正常遍历
Object.keys(reg).forEach(key => {
  console.log(`属性名:${key},值:${reg[key]}`);
});

方案2:创建包含所有属性的普通对象(无副作用)

如果不想修改原对象的属性描述符,更安全的方式是创建一个普通对象,把原对象(包括原型链上)的所有属性拷贝进去:

function getEnumerableClone(obj) {
  const clone = {};
  let currentObj = obj;
  while (currentObj !== null) {
    Object.getOwnPropertyNames(currentObj).forEach(prop => {
      clone[prop] = currentObj[prop];
    });
    currentObj = Object.getPrototypeOf(currentObj);
  }
  return clone;
}

// 使用示例
const enumerableReg = getEnumerableClone(reg);
Object.keys(enumerableReg).forEach(key => {
  console.log(`属性名:${key},值:${enumerableReg[key]}`);
});

注意事项

  • 浏览器宿主对象(如ServiceWorkerRegistration)的属性不可枚举是浏览器的设计规范,修改其属性描述符可能存在未知风险,建议在测试环境充分验证后再投入生产。
  • 方案2无需修改原对象,避免了潜在副作用,更适合大多数场景。

内容的提问来源于stack exchange,提问作者Null Salad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 05:25:26