You need to enable JavaScript to run this app. 如何检查JavaScript对象中是否存在可被赋值的属性
优惠活动
大模型
产品
解决方案
定价
更多

如何检查JavaScript对象中是否存在可被赋值的属性

解决方案

你遇到的问题核心是in关键字仅能判断属性是否存在于对象或其原型链上,无法校验属性是否支持赋值,所以遇到仅定义了getter的访问器属性时就会触发报错。你可以通过以下两种方案解决:

方案1:通过属性描述符判断可写性

通过Object.getOwnPropertyDescriptor顺着原型链查找对应属性的描述符,判断属性是否支持赋值:

/**
 * 检查对象指定属性是否可被赋值
 * @param {object} obj 目标对象
 * @param {string} propName 要检查的属性名
 * @returns {boolean} 属性是否可写
 */
function isPropertyWritable(obj, propName) {
  // 已冻结的对象所有属性不可写
  if (Object.isFrozen(obj)) return false;

  let currentProto = obj;
  // 顺着原型链查找属性描述符
  while (currentProto) {
    const descriptor = Object.getOwnPropertyDescriptor(currentProto, propName);
    if (descriptor) {
      // 数据属性判断writable配置,访问器属性判断是否存在setter
      return 'writable' in descriptor ? descriptor.writable : !!descriptor.set;
    }
    currentProto = Object.getPrototypeOf(currentProto);
  }

  // 若属性不存在,默认返回false(和原`in`判断逻辑保持一致:仅存在的属性才赋值)
  // 如果需要支持属性不存在时新增赋值,可改为 return !Object.isSealed(obj);
  return false;
}

使用时替换原有的in判断即可:

const obj = new MyClass();
const value = '你要赋的值';
if (isPropertyWritable(obj, 'property')) {
  obj.property = value;
}

方案2:try-catch兜底赋值

如果你的场景中存在Proxy代理对象、第三方封装对象等无法通过属性描述符判断的情况,可以直接用try-catch包裹赋值逻辑,容错性更强:

const obj = new MyClass();
const value = '你要赋的值';
try {
  obj.property = value;
} catch (e) {
  // 仅捕获赋值权限类错误,其他错误正常抛出
  if (!(e instanceof TypeError && e.message.includes('Cannot set property'))) {
    throw e;
  }
  // 可选:添加日志记录赋值失败的情况
  console.warn(`属性<property>不可赋值,已忽略`);
}

两种方案可以根据你的实际场景选择:

  • 常规业务场景下优先选方案1,性能更高且无副作用
  • 处理不确定类型的第三方对象时选方案2,兼容性更强

内容的提问来源于stack exchange,提问作者Nicholas Chiang

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.16 17:27:05