我刚刚使用Leaflet为网站构建 map ,并注意到要添加平铺图层,至少可以使用两种方法L.TileLayer()L.tileLayer(),它们的名称仅在单个字符的情况下有所不同。
但是,虽然可以将这两种方法返回的对象添加到L.map()返回的 map 对象,但是L.TileLayer()返回的对象似乎没有addTo()方法,而L.tileLayer()返回的对象似乎没有L.tileLayer()方法。例如。都

var map = L.map('map');
var tiles = new L.TileLayer(<tileUrl>, {attribution: <tileAttrib>});
map.addLayer(tiles);
var map = L.map('map');
var tiles = new L.tileLayer(<tileUrl>, {attribution: <tileAttrib>});
map.addLayer(tiles);
以及
var map = L.map('map');
L.tileLayer(<tileUrl>, {attribution: <tileAttrib>}).addTo(map);
同时
var map = L.map('map');
L.TileLayer(<tileUrl>, {attribution: <tileAttrib>}).addTo(map);
失败。浏览Leaflet的文档,似乎使用的正确方法是L.TileLayer(),因此问题是ojit_code的用途是什么?
到目前为止,这是我的代码的完整示例,尝试使用不同的替代方法只是取消注释要测试的注释,并确保其他注释已注释
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
   <head>
      <meta http-equiv="content-type" content="text/html; charset=iso-8859-1"/>
      <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"/>

      <link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css"
            integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ=="
            crossorigin=""/>
      <script src="https://unpkg.com/[email protected]/dist/leaflet.js"
            integrity="sha512-tAGcCfR4Sc5ZP5ZoVz0quoZDYX5aCtEm/eu1KhSLj2c9eFrylXZknQYmxUssFaVJKvvc0dJQixhGjG2yXWiV9Q=="
            crossorigin=""> </script>
   </head>
   <body onload="makeMap()">
      <script type="text/javascript">
         function makeMap() {
            var tileUrl = 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
            var tileAttrib = 'Map data &copy <a href="https://openstreetmap.org">OpenStreetMap</a> contributors';
            var map = L.map('map').setView([63,15],9);

            // using tileLayer and addLayer - this works
            var tiles = new L.tileLayer(tileUrl, {attribution: tileAttrib});
            map.addLayer(tiles);

            // using tileLayer and addTo - this works
//             L.tileLayer(tileUrl, {attribution: tileAttrib}).addTo(map);

            // using TileLayer and addLayer - this works
//             var tiles = new L.TileLayer(tileUrl, {attribution: tileAttrib});
//             map.addLayer(tiles);

            // using TileLayer and addTo - this fails
//             L.TileLayer(tileUrl, {attribution: tileAttrib}).addTo(map);
         }

      </script>
      <table border=1 style="position: absolute; top: 0; bottom: 0; left: 0; right: 0; width: 100%; height: 100%;">
         <tr style="height: 100%;">
            <td>
               <div id="map" style="width: 100%; height: 100%;"></div>
            </td>
         </tr>
      </table>
   </body>
</html>

最佳答案

TL; DR:
这两个都是有效且等效的:

var foo = L.tileLayer(arguments);
var foo = new L.TileLayer(arguments);
这两个在语法上是有效的(由于Javascript的历史包bag),但最终会导致错误:
var foo = new L.tileLayer(arguments);
var foo = L.TileLayer(arguments);


好吧,它们实际上不是两种方法。从技术上讲,L.TileLayerObject的实例,而L.tileLayerFunction的实例,它继承了Object的原型(prototype)。 L充当 namespace 而不是类实例。
您会发现,使用Java进行面向对象的编程很奇怪。您可以将 new keyword与几乎所有具有原型(prototype)的对象一起使用。对于大多数精通“适当” OOP的人来说,prototype-based inheritance令人困惑。
如今,使用ES2015标准和奇特的class关键字,这实际上不是问题(我想说这是一个问题,但隐藏在语法糖层之下)。但是在过去,开发人员不得不求助于creative solutions for class inheritance,有时它涉及messing with the prototype chain
Leaflet使用了这些方法的组合-作为不希望的副作用,L.TileLayer变成了Function,人们可以直接调用L.TileLayer(),这非常令人困惑。
Leaflet还使用了factory functions的概念:一个返回类实例的函数。引用one of the Leaflet tutorials:

这只是为了方便:它避免了用户在担心new关键字的时代再次输入new关键字。
但这会产生另一个不良影响,因为在Javascript中,所有Function都有一个原型(prototype),这意味着您可以执行以下操作
 function myFunction() { ... }
 var wtf = new myFunction();
因此,new L.tileLayer()也是有效的语法(但在运行时失败)。


再次,L.TileLayer()作为函数调用是不希望的副作用。但是L.TileLayer代表一个类,由于以下原因,对其进行引用很重要:
 if (layer instanceof L.TileLayer)

08-19 05:07