Reputation: 65
I'm trying to invoke a method using callbacks and object orientated javascript dealing with google api, but I keep getting an undefined error with the function being called.
js:
var generateMap = (function(){
var map;
return{
offsetCenter: function(lat, lng){
lat = lat;
lng = lng + .01;
return new google.maps.LatLng(lat, lng);
}
,initialize: function(location){
console.log("test");
var latLng = new google.maps.LatLng(location.coords.latitude, location.coords.longitude);
var mapOptions = {
zoom: 15,
center: latLng,
mapTypeId: google.maps.MapTypeId.ROADMAP,
disableDefaultUI: true,
draggable: false,
scaleControl: false,
scrollwheel: false
};
map = new google.maps.Map(document.getElementById('map'), mapOptions);
var newCenter = offsetCenter(location.coords.latitude, location.coords.longitude);
map.setCenter(newCenter);
var marker = new google.maps.Marker({
position: new google.maps.LatLng(location.coords.latitude, location.coords.longitude),
title: 'Point A',
map: map,
draggable: false
});
}
,createMap: function(){
navigator.geolocation.getCurrentPosition(initialize);
}
};
})();
$(document).ready(function(){
var callbacks = $.Callbacks();
callbacks.add(
generateMap.createMap
);
callbacks.fire();
})
Error: ReferenceError: initialize is not defined
Any reason why this could be happening?
Upvotes: 0
Views: 1061
Reputation: 1075895
The main problem is that createMap
refers to a symbol that isn't defined:
,createMap: function(){
navigator.geolocation.getCurrentPosition(initialize);
// Here ---------------------------------^
}
Unlike Java or C#, JavaScript has no implied this
for methods on the current instance. You have to specify it.
Now, because generateMap
is a singleton, and initialize
doesn't use this
anywhere, you can correct it like this:
,createMap: function(){
navigator.geolocation.getCurrentPosition(generateMap.initialize);
}
Again, that only works because generateMap
is a singleton, and initialize
doesn't use this
.
In the general case (if it weren't a singleton, or initialize
used this
), you'd manage this
:
This code:
callbacks.add(
generateMap.createMap
);
...will add a reference to the createMap
function to the callbacks list, but that function isn't in any way bound to the generateMap
object. So when it's called, this
won't refer to generateMap
(other than closing over it, but again, we're assuming here we aren't dealing with a singleton). You can fix that with ES5's Function#bind
or jQuery's $.proxy
:
callbacks.add(
generateMap.createMap.bind(generateMap)
);
// or
callbacks.add(
$.proxy(generateMap.createMap, generateMap)
);
Each of those creates a function that, when called, will turn around and call createMap
making this = generateMap
during the call.
Then in createMap
, we fix the initialize
thing in a similar way:
,createMap: function(){
navigator.geolocation.getCurrentPosition(this.initialize.bind(this));
}
// or
,createMap: function(){
navigator.geolocation.getCurrentPosition($.proxy(this.initialize, this));
}
More about this
in JavaScript on my blog:
Upvotes: 1