不推荐直接扩展内置对象原型,因会污染全局环境、引发命名冲突和调试困难;应优先使用工具函数、命名空间或模块导入;若必须扩展,须先检测原生支持且不覆盖已有方法。

可以直接往 Array.prototype 或 String.prototype 上添加函数,让所有数组或字符串实例自动拥有这个方法。但要注意——这不是推荐做法,仅在明确知道风险且可控时才用。
怎么写:原型赋值是唯一可行方式
内置对象的原型不能整体替换(比如 Array.prototype = {}),否则会报错或失效。只能逐个挂载方法:
Array.prototype.sum = function() { return this.reduce((a, b) => a + b, 0); };String.prototype.firstChar = function() { return this.charAt(0); };- 调用时直接
[1,2,3].sum()或"hello".firstChar(),无需 new 或额外包装
为什么通常不建议这样做
原型是全局共享的,一旦添加,影响整个运行环境:
- 第三方库或未来浏览器原生方法可能同名(比如你写了
Array.prototype.groupBy,而 ES2024 已正式支持它) - 不同团队或模块各自扩展,容易覆盖或行为不一致,引发静默 bug
- SSR、微前端等场景下,原型状态难以隔离,调试困难
- TypeScript 和 ESLint 默认会警告甚至禁止这类操作(如
no-extend-native规则)
更安全的替代方案
绝大多数情况下,优先选择不污染原型的方式:
立即学习“Java免费学习笔记(深入)”;
-
工具函数:写成独立函数,如
function sum(arr) { return arr.reduce(...); },调用清晰无副作用 -
命名空间封装:比如
ArrayUtils.sum([1,2,3]),避免全局污染 -
ES 模块按需导入:
import { compact } from './array-helpers.js',支持 tree-shaking -
Symbol 命名(极少用):用
const myMethod = Symbol('myMethod')挂到 prototype 上,避免字符串冲突,但依然改变原型,不解决根本问题
如果真要扩展,必须遵守的底线
仅限极少数场景,例如填补已标准化但环境不支持的 API(如旧版 Safari 缺少 Promise.prototype.finally):
- 先检测原生是否存在:
if (!Array.prototype.flat) { Array.prototype.flat = ... } - 不覆盖已有方法,不修改非标准属性,不依赖
this的意外类型(比如防止字符串方法被数字调用) - 确保项目完全自控、无第三方脚本、有完整测试覆盖和静态分析


















