Google 映射 JS 代码 - "this.activeInfoWindow.close()" - 作用域 & this

Google map JS code - "this.activeInfoWindow.close()" - scope & this

在以下 Google 映射 JS 代码中,"this.activeInfoWindow.close()" 语句未按预期工作。我想我在这里遗漏了一些重要的范围界定原则。有一个更好的方法吗?

我正在努力学习更好的命名空间和作用域以及 OO 技术。

    var data = {
      "cities": [{
        "cityCntrLat": "45.49463",
        "cityCntrLng": "-73.57819",
        "censusName": "MONTREAL"
      }, {

        "cityCntrLat": "43.65674",
        "cityCntrLng": "-79.39819",
        "censusName": "TORONTO"
      }, {
        "cityCntrLat": "46.80807",
        "cityCntrLng": "-71.21964",
        "censusName": "QUEBEC"
      }]
    };


    $(document).ready(function() {

      var myApplication = {

        // variable to hold a map
        map: undefined,

        // variable to hold current active InfoWindow
        activeInfoWindow: undefined,

        // arrays to hold copies of the cities markers
        gmarkers_cities: [],

        // ------------------------------------------------------------------------------- //
        // initialize function      
        // ------------------------------------------------------------------------------- //
        initialize: function() {

          // map options - lots of options available here 
          var mapOptions = {
            zoom: 5,
            draggable: true,
            center: new google.maps.LatLng(45.64378, -73.50497),
            mapTypeId: google.maps.MapTypeId.ROADMAP
          };

          // create map in div called map-canvas using map options defined above
          map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);

          var markerData = data.cities
          for (var i = 0; i < markerData.length; i++) {
            var myMarker = new google.maps.LatLng(markerData[i]['cityCntrLat'], markerData[i]['cityCntrLng']);
            var myArray = {};
            myArray = {
              "available": markerData[i]['available']
            };

            this.fnPlaceMarkers(myArray, myMarker, markerData[i]['censusName'], "red");

          }; // end for

        },

        // ------------------------------------------------------------------------------- //
        // create markers on the map
        // ------------------------------------------------------------------------------- //       
        fnPlaceMarkers: function(myArray, myLocation, myCityName, fillColour) {

          // create SVG icon that looks like a flag
          // The lowercase 'm' is "relative" moveto
          // the lowercase 'z' closes the path
          // more on SVG path command: http://www.w3.org/TR/SVG/paths.html

          var myIcon = {
            path: 'M  0,0,  0,-40,  20,-30 , 0,-20,  z',
            fillColor: fillColour,
            fillOpacity: 0.7,
            scale: 1,
            strokeColor: 'black',
            strokeWeight: 2
          };

          // clone myIcon (not sure if there is better way to do this?)
          var myOtherIcon = jQuery.extend({}, myIcon);

          myOtherIcon.fillColor = "blue";

          // create marker and put it on map
          var marker = new google.maps.Marker({
            position: myLocation,
            icon: myIcon,
            map: map
          });

          // create an InfoWindow
          var infoWnd = new google.maps.InfoWindow();

          // add content to your InfoWindow
          infoWnd.setContent('<div class="scrollFix">' + 'Welcome to ' + myCityName + '</div>');

          // add listener on InfoWindow - close last infoWindow  before opening new one 
          google.maps.event.addListener(marker, 'click', function() {

            // Close active window if exists                                
            // WHY DOES THIS NOT WORK??
            if (typeof this.activeInfoWindow != 'undefined') {
              this.activeInfoWindow.close();
            };
            console.log(typeof this.activeInfoWindow);

            // Open InfoWindow
            infoWnd.open(map, marker);

            // Store new open InfoWindow in global variable
            this.activeInfoWindow = infoWnd;
            //console.log(this.activeInfoWindow);
          });

          // keep extra copy of marker info
          marker.available = myArray['available'];
          this.gmarkers_cities.push(marker);
        }


      };
      myApplication.initialize();

    }); // end jquery
#map-canvas {
  height: 350px;
  width: 600px;
}
table {
  border-collapse: collapse;
}
td {
  border: 1px solid #B0B0B0;
  padding: 5px;
  background-color: #F8F8F8;
}
<html>
<script src="http://maps.googleapis.com/maps/api/js" type="text/javascript"></script>
<!-- <script src="../jquery/jquery.js" type="text/javascript"></script>  -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<!-- <script src="data.json" type="text/javascript"></script>           -->

<table>
  <tr>
    <td>
      <div id="map-canvas"></div>
    </td>

  </tr>
</table>

在函数内部使用 "this" 不会 return 您的主要对象。我通过删除 this.activeInfoWindow 并将其更改为 myApplication.activeInfoWindow 更改了您的代码,现在它按预期工作了。

var data = {
  "cities": [{
    "cityCntrLat": "45.49463",
    "cityCntrLng": "-73.57819",
    "censusName": "MONTREAL"
  }, {

    "cityCntrLat": "43.65674",
    "cityCntrLng": "-79.39819",
    "censusName": "TORONTO"
  }, {
    "cityCntrLat": "46.80807",
    "cityCntrLng": "-71.21964",
    "censusName": "QUEBEC"
  }]
};


$(document).ready(function() {

  var myApplication = {

    // variable to hold a map
    map: undefined,

    // variable to hold current active InfoWindow
    activeInfoWindow: undefined,

    // arrays to hold copies of the cities markers
    gmarkers_cities: [],

    // ------------------------------------------------------------------------------- //
    // initialize function      
    // ------------------------------------------------------------------------------- //
    initialize: function() {

      // map options - lots of options available here 
      var mapOptions = {
        zoom: 5,
        draggable: true,
        center: new google.maps.LatLng(45.64378, -73.50497),
        mapTypeId: google.maps.MapTypeId.ROADMAP
      };

      // create map in div called map-canvas using map options defined above
      map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);

      var markerData = data.cities
      for (var i = 0; i < markerData.length; i++) {
        var myMarker = new google.maps.LatLng(markerData[i]['cityCntrLat'], markerData[i]['cityCntrLng']);
        var myArray = {};
        myArray = {
          "available": markerData[i]['available']
        };

        this.fnPlaceMarkers(myArray, myMarker, markerData[i]['censusName'], "red");

      }; // end for

    },

    // ------------------------------------------------------------------------------- //
    // create markers on the map
    // ------------------------------------------------------------------------------- //     

    fnPlaceMarkers: function(myArray, myLocation, myCityName, fillColour) {

      // create SVG icon that looks like a flag
      // The lowercase 'm' is "relative" moveto
      // the lowercase 'z' closes the path
      // more on SVG path command: http://www.w3.org/TR/SVG/paths.html

      var myIcon = {
        path: 'M  0,0,  0,-40,  20,-30 , 0,-20,  z',
        fillColor: fillColour,
        fillOpacity: 0.7,
        scale: 1,
        strokeColor: 'black',
        strokeWeight: 2
      };

      // clone myIcon (not sure if there is better way to do this?)
      var myOtherIcon = jQuery.extend({}, myIcon);

      myOtherIcon.fillColor = "blue";

      // create marker and put it on map
      var marker = new google.maps.Marker({
        position: myLocation,
        icon: myIcon,
        map: map
      });

      // create an InfoWindow
      var infoWnd = new google.maps.InfoWindow();

      // add content to your InfoWindow
      infoWnd.setContent('<div class="scrollFix">' + 'Welcome to ' + myCityName + '</div>');

      // add listener on InfoWindow - close last infoWindow  before opening new one 
      google.maps.event.addListener(marker, 'click', function() {

        // Close active window if exists                                
        // WHY DOES THIS NOT WORK??
        if (typeof  myApplication.activeInfoWindow != 'undefined') {
          myApplication.activeInfoWindow.close();
        };


        // Open InfoWindow
        infoWnd.open(map, marker);

        // Store new open InfoWindow in global variable
         myApplication.activeInfoWindow = infoWnd;
        //console.log(this.activeInfoWindow);
      });

      // keep extra copy of marker info
      marker.available = myArray['available'];
      this.gmarkers_cities.push(marker);
    }


  };
  myApplication.initialize();

}); // end jquery
#map-canvas {
   height: 350px;
   width: 600px;
 }
 table {
   border-collapse: collapse;
 }
 td {
   border: 1px solid #B0B0B0;
   padding: 5px;
   background-color: #F8F8F8;
 }
<html>
<script src="http://maps.googleapis.com/maps/api/js" type="text/javascript"></script>
<!-- <script src="../jquery/jquery.js" type="text/javascript"></script>  -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<!-- <script src="data.json" type="text/javascript"></script>           -->


<table>
  <tr>
    <td>
      <div id="map-canvas"></div>
    </td>
  </tr>
</table>