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

Object.assign扩展Array.prototype报this.map非函数TypeError原因

核心差异与报错原因解析

两种Array.prototype扩展方案的核心差异

两种方案的本质区别是对属性(尤其是访问器属性getter/setter)的复制、挂载逻辑完全不同:

  • Object.assign 方案:只会读取源对象所有可枚举自有属性的值,再写入目标对象,不会复制属性的底层描述符。遇到源对象上的getter,会在复制阶段立即执行getter拿到返回值,再把返回值作为普通数据属性写到目标上,根本不会把getter本身挂载到目标对象。同时该方法复制的属性默认都是可写、可枚举、可配置的。
  • 直接赋值+Object.defineProperty 方案:直接给原型赋值方法,是把函数作为普通数据属性挂载;defineProperty可以精确配置属性的底层描述符,能把getter/setter逻辑完整挂载到目标对象上,不会提前触发getter执行。如果不手动指定属性配置项,该方法定义的属性默认是不可写、不可枚举、不可配置的。

Object.assign方案报错的根本原因

报错根本不是发生在后续调用m.max()的阶段,而是Object.assign(Array.prototype, {...})执行的瞬间就触发了错误,完整触发流程如下:

  1. 传入Object.assign的第二个参数是普通对象字面量,其中maxRowLength是用get语法定义的访问器属性。
  2. Object.assign处理到maxRowLength属性时,不会把这个getter挂载到Array.prototype上,而是先在源对象字面量的上下文里执行这个getter,准备拿到返回值后再赋值给Array.prototype。
  3. 此时getter内部的this指向的是源对象字面量本身(一个普通Object实例,不是数组),执行到this.max(row => row.length)时,会调用源对象自有的max方法,max方法内部的this依然指向这个普通对象。
  4. 普通对象没有数组原型上的map方法,执行到this.map(...)时直接抛出TypeError: this.map is not a function,整个Object.assign执行中断,后续的测试代码自然无法运行。

补充:一次性挂载方法和getter的正确写法

Object.assign本身不支持复制访问器描述符,如果要实现批量挂载包含getter/setter的属性,可以用属性描述符相关API实现:

Object.defineProperties(
  Array.prototype,
  Object.getOwnPropertyDescriptors({
    max(mapf = (x) => x) {
      return Math.max(...this.map(x => mapf(x)));
    },
    get maxRowLength() {
      return this.max(row => row.length);
    }
  })
);

这种写法会把源对象的所有属性描述符(包括getter、可枚举性等配置)完整复制到Array.prototype上,不会提前触发getter执行,和手动实现的第二种方案效果一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 22:33:01