0

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?

1 Answer 1

1

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:

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.