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

扩展Object、String原型时Mocha测试抛出TypeError异常的问题排查

问题原因分析

这个错误的核心是属性描述符冲突:当你直接给Object.prototype.contains赋值时,本质是在用数据描述符(包含value和writable属性)定义这个属性,但你的测试环境中(比如Mocha、Chai或其他依赖库)已经通过Object.defineProperty给Object.prototype添加了contains属性,并且使用了访问器描述符(即get/set方法)。JavaScript不允许同一个属性同时拥有访问器描述符和数据描述符,因此触发了这个类型错误。

而Azure函数运行环境中没有第三方库修改Object.prototype的contains属性,所以你的代码能正常运行。

解决方案

我推荐三种解决思路,按优先级排序:

1. 避免修改内置对象原型(最佳实践)

修改内置对象的原型是公认的不良实践,容易引发命名冲突、for...in循环污染等问题。你可以把这些逻辑改成独立的工具函数:

// utils.ts
export const stringContains = (str: string, substr: string): boolean => {
  return str.includes(substr);
};

export const objectContains = (obj: object, key: string): boolean => {
  // 用call避免obj重写hasOwnProperty的情况
  return Object.prototype.hasOwnProperty.call(obj, key);
};

然后在业务代码中替换原型调用:

import { stringContains, objectContains } from './utils';
// 如果不再用原型方法,可以删除下面这行
// import 'custom/prototype/file';

export const myFunction: Function = (s: string): Object => {
 const bool: boolean = stringContains(s, 'look for this string');
 const obj = { name: "string" };
 const fbool: boolean = objectContains(obj, 'name');
 return { foo: s, fboo: fbool };
}

2. 安全地修改原型(如果必须保留原型方法)

如果你一定要保留原型方法,需要先检查属性是否存在,并用Object.defineProperty显式定义描述符,确保和已有描述符兼容:

declare global {
 interface String { contains(s: string): boolean; }
 interface Object { contains(s: string): boolean; }
}

// String原型扩展
if (!String.prototype.hasOwnProperty('contains')) {
  Object.defineProperty(String.prototype, 'contains', {
    value: function(this: string, s: string): boolean {
      return this.includes(s);
    },
    writable: true,
    enumerable: false, // 关键:避免污染for...in循环
    configurable: true
  });
}

// Object原型扩展
if (!Object.prototype.hasOwnProperty('contains')) {
  Object.defineProperty(Object.prototype, 'contains', {
    value: function(this: object, s: string): boolean {
      return Object.prototype.hasOwnProperty.call(this, s);
    },
    writable: true,
    enumerable: false,
    configurable: true
  });
}

export {};

这里的关键点:

  • 用hasOwnProperty检查属性是否已存在,避免重复定义
  • 设置enumerable: false,防止原型方法出现在for...in循环中
  • 显式定义描述符,避免和已有属性的描述符冲突

3. 排查测试环境依赖

你可以检查测试环境的依赖包,看看是哪个库修改了Object.prototype的contains属性。比如查看node_modules中的库代码,或者升级/替换冲突的依赖。不过这种方法比较繁琐,优先级低于前两种。

内容的提问来源于stack exchange,提问作者Kim Kong

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 05:24:06