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

升级Google Maps JS API v3.58+后自定义Polyline类报错求助

问题描述

地图应用升级至Google Maps JavaScript API v3.58及以上版本后出现故障,自定义继承google.maps.Polyline的类无法正常实例化。

控制台报错

TypeError: Class constructors cannot be invoked without 'new'
at new CustomPolyline.Polyline (webpack-internal:///...tomPolygon.js:31:32)

实例化代码

polylines.push(new CUST.CustomPolyline.Polyline(polygonType, this.mapInstance, polylineJSONObjects[i].coordinates, polylineJSONObjects[i].normalPolyAttributes, polylineJSONObjects[i].highlightPolyAttributes, polylineJSONObjects[i].normalPolyAttributes.mapLabelText));

自定义类核心代码

'use strict';
(
  function (window, CUST, google) {

  if (typeof (CUST) === 'undefined') {
    CUST = {};
  }

  CUST.CustomPolyline.Polyline = function(polyType, googleMap, dvgCoordinatesString, 
                                       normalPolyAttributes, highlightPolyAttributes,
                                       labelText) {
  // Constructor
  if (this instanceof CustomPolyline.Polyline) {
    try {
      google.maps.Polyline.apply(this, arguments);
    } catch (ex) {
      // new Chrome update gave exception in 'apply' so used 'call'
      google.maps.Polyline.call(this, arguments);
    }

    this.base = google.maps.Polyline.prototype;

    <... constructor initialization code ...>
  }
 
  <... extension methods ...>

)(window, window.CUST, window.google);

补充信息

  • v3.57版本可正常运行,v3.58及以上版本触发错误
  • 查阅官方发布说明未找到相关破坏性变更记录
  • 疑问:是否为ECMAScript版本问题?如何在不重写数千行扩展类的前提下修复?

问题分析与修复方案

根本原因

Google Maps JavaScript API v3.58及以上版本中,google.maps.Polyline从原有的构造函数模式改为了ES6类模式。ES6类的构造函数必须通过new关键字调用,而原有代码通过apply/call直接调用父类构造函数、试图在自定义实例上执行父类逻辑的方式,违反了ES6类的调用规则,因此抛出错误。

修复方案(无需重写大量代码)

方案1:兼容ES5环境的实例继承改造

修改自定义类的构造逻辑,先创建原生Polyline实例,再挂载自定义原型与属性,保留原有命名空间和方法:

'use strict';
(
  function (window, CUST, google) {

  if (typeof (CUST) === 'undefined') {
    CUST = {};
  }

  // 提取原自定义方法到原型对象
  const customPolylineMethods = {
    // 把原<... extension methods ...>中的方法移到此处
    // 示例:
    toggleHighlight() {
      // ...原有高亮逻辑
    },
    updateLabel() {
      // ...原有标签更新逻辑
    }
  };

  CUST.CustomPolyline.Polyline = function(polyType, googleMap, dvgCoordinatesString, 
                                       normalPolyAttributes, highlightPolyAttributes,
                                       labelText) {
    if (!(this instanceof CUST.CustomPolyline.Polyline)) {
      return new CUST.CustomPolyline.Polyline(...arguments);
    }

    // 转换为原生Polyline要求的options参数格式
    const polylineOptions = {
      map: googleMap,
      path: dvgCoordinatesString, // 需确保是LatLng数组,必要时做格式转换
      ...normalPolyAttributes
    };

    // 创建原生Polyline实例
    const polylineInstance = new google.maps.Polyline(polylineOptions);

    // 挂载自定义原型链,确保继承原生方法+自定义方法
    Object.setPrototypeOf(customPolylineMethods, google.maps.Polyline.prototype);
    Object.setPrototypeOf(polylineInstance, customPolylineMethods);

    // 挂载自定义属性与原有初始化逻辑
    polylineInstance.polyType = polyType;
    polylineInstance.highlightPolyAttributes = highlightPolyAttributes;
    polylineInstance.labelText = labelText;
    polylineInstance.base = google.maps.Polyline.prototype;

    // 执行原<... constructor initialization code ...>逻辑
    // ...原有初始化代码

    return polylineInstance;
  };

  // 确保自定义类的原型指向正确,兼容原有实例判断逻辑
  Object.assign(CUST.CustomPolyline.Polyline.prototype, customPolylineMethods);
  Object.setPrototypeOf(CUST.CustomPolyline.Polyline.prototype, google.maps.Polyline.prototype);

})(window, window.CUST, window.google);

方案2:ES6类语法封装(环境支持ES6时优先)

用class extends语法封装原有逻辑,最小化代码改动:

'use strict';
(
  function (window, CUST, google) {

  if (typeof (CUST) === 'undefined') {
    CUST = {};
  }

  class CustomPolyline extends google.maps.Polyline {
    constructor(polyType, googleMap, dvgCoordinatesString, 
                normalPolyAttributes, highlightPolyAttributes,
                labelText) {
      // 转换为原生Polyline要求的options参数
      const polylineOptions = {
        map: googleMap,
        path: dvgCoordinatesString,
        ...normalPolyAttributes
      };
      // 调用父类构造函数
      super(polylineOptions);

      // 执行原有初始化逻辑
      this.polyType = polyType;
      this.highlightPolyAttributes = highlightPolyAttributes;
      this.labelText = labelText;
      this.base = google.maps.Polyline.prototype;

      <... constructor initialization code ...>
    }

    // 直接迁移原<... extension methods ...>中的方法
    toggleHighlight() {
      // ...原有高亮逻辑
    }
  }

  CUST.CustomPolyline.Polyline = CustomPolyline;

})(window, window.CUST, window.google);

关键注意事项

  • 原生google.maps.Polyline的构造函数仅接受一个options对象,原有代码传入的零散参数必须先转换为符合要求的格式,否则原生Polyline无法正常初始化。
  • 两种方案均保留了原有命名空间CUST.CustomPolyline.Polyline,因此实例化代码无需修改。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 02:24:51