Javascript 销毁地图实例的正确方法是什么?

Javascript 销毁地图实例的正确方法是什么?,javascript,google-maps-api-3,Javascript,Google Maps Api 3,我最近开发了一个html5移动应用程序。应用程序是一个页面,其中导航哈希更改事件替换了整个DOM。应用程序的一部分是使用API v3的Google地图。在从DOM中删除map div之前,我想删除任何事件处理程序/侦听器,并释放尽可能多的内存,因为用户可能不会再次返回该部分 销毁地图实例的最佳方法是什么?当您删除div时,将删除显示面板,地图将消失。要删除映射实例,只需确保对映射的引用设置为null,对映射其他部分的引用设置为null。此时,JavaScript垃圾收集将负责清理,如中所述:。我

我最近开发了一个html5移动应用程序。应用程序是一个页面,其中导航哈希更改事件替换了整个DOM。应用程序的一部分是使用API v3的Google地图。在从DOM中删除map div之前,我想删除任何事件处理程序/侦听器,并释放尽可能多的内存,因为用户可能不会再次返回该部分


销毁地图实例的最佳方法是什么?

当您删除
div
时,将删除显示面板,地图将消失。要删除映射实例,只需确保对映射的引用设置为
null
,对映射其他部分的引用设置为
null
。此时,JavaScript垃圾收集将负责清理,如中所述:。

我想您所说的是
addEventListener
。删除DOM元素时,某些浏览器会泄漏这些事件,而不会删除它们。这就是为什么jQuery在删除元素时会执行以下操作:

  • 它可以使用
    removeEventListener
    删除事件。这意味着它将保留一个包含它添加到此元素上的事件侦听器的数组
  • addEventListener
    不可用时(仍然有一个存储添加事件的数组),它使用DOM元素上的
    delete
    删除事件属性(
    onclick
    onblur
    等)
  • 它将元素设置为
    null
    ,以避免IE 6/7/8内存泄漏
  • 然后删除该元素

我会建议删除map div的内容,并对保存map引用的变量使用
delete
,并且可能会显式地
delete
调用任何事件侦听器


不过,这可能不起作用。

我在这个问题上添加了第二个答案,因为我不想删除我们通过对我先前答案的后续评论所做的反复

但我最近遇到了一些直接解决你问题的信息,所以我想与大家分享。我不知道你是否意识到了这一点,但在会议期间,谷歌的克里斯·布罗德福特和卢克·马厄从stackoverflow讨论了这个问题。如果您将视频播放设置为12:50,则这是他们讨论您的问题的部分

本质上,他们承认这是一个bug,但也补充说,他们并不真正支持涉及创建/销毁连续映射实例的用例。他们强烈建议创建映射的单个实例,并在任何此类场景中重用它。他们还讨论了将映射设置为null,并显式删除事件侦听器。您表达了对事件侦听器的关注,我认为只需将map设置为null就足够了,但您的关注似乎是有效的,因为它们特别提到了事件侦听器。他们还建议完全删除保存地图的DIV


无论如何,我只是想把它传递给大家,确保它包含在stackoverflow讨论中,并希望它能帮助你和其他人-

因为谷歌没有为api v3提供gunload(),所以最好在html中使用iframe,并将map.html作为这个iframe的源。使用后,将src设置为null。这肯定会释放map所消耗的内存。

因为显然您无法真正销毁map实例,如果

  • 您需要在一个网站上同时显示多个地图
  • 地图的数量可能会随着用户交互而变化
  • 地图需要隐藏,并与其他组件一起重新显示(即它们在DOM中不显示在固定位置)
正在保留一个映射实例池。 该池跟踪正在使用的实例,当请求一个新实例时,它检查是否有任何可用的映射实例是空闲的:如果是,它将返回一个现有的实例,如果不是,它将创建一个新的映射实例并返回,并将其添加到池中。这样,您的最大实例数将仅等于您在屏幕上同时显示的最大地图数。 我正在使用以下代码(它需要jQuery):

跑步

google.maps.event.clearInstanceListeners(divReference[0]);
divReference.detach()
(其中divReference是从实例池返回的div的jQuery对象) 在我删除的每一个div中,我都设法使Chrome的内存使用或多或少保持稳定,而不是每次删除地图和添加新地图时内存都会增加。

问题在于你没有。应重用单页应用程序中的映射实例,而不是先销毁再重新创建


对于某些单页应用程序,这可能意味着重新设计解决方案,以便在创建映射后,可以将其隐藏或断开与DOM的连接,但它永远不会被销毁/重新创建。

我不确定将map变量设置为null是否会正确删除所有事件侦听器。必须设置为
null
的不仅仅是map,还有对其他任何内容的引用。因此,如果将标记引用设置为
null
,使其无法访问,则无法访问事件侦听器。它可能仍然连接到地图,但地图无法访问,因此它只是一大块基本上已成为孤儿的内存。这与设置
数组相同。长度=0
;如果没有其他对成员的引用,它们只会形成一组孤立内存,可以进行垃圾收集。可以使用中记录的API事件方法添加/删除/触发它们。虽然在功能上与浏览器addEventListener类似,但仍有大量特定于映射的自定义事件(如“bounds_changed”),其中一些事件处理程序与浏览器事件挂钩,如映射“resize”然后保留一个添加和删除的事件数组,然后使用
removeEventListener
d手动执行
google.maps.event.clearInstanceListeners(window);
google.maps.event.clearInstanceListeners(document);
google.maps.event.clearInstanceListeners(divReference[0]);
divReference.detach()