Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript

Michael Williams
PLUS
Michael Williams
Courses Plus Student 8,059 Points

Why can you write a function after it's called, and it will still work, yet other code has to be written sequentially?

For example, check out the HTML below. Specifically, the populateInfoWindow function. It's declared after it's been called but still works properly. Yet there's other code (I'm lacking an example at the moment) that has to be written sequentially in order to work. Why? Is there a rule of thumb for both situations?

<!-- This is the corresponding "starter code" for 04_Hello Map in Udacity and Google's Maps
API Course, Lesson 1 -->
<html>
 <head>
 <!-- styles put here, but you can include a CSS file and reference it instead! -->
   <style type="text/css">
     html, body { height: 100%; margin: 0; padding: 0; }
     #map { 
         bottom: 0px;
         height: 100%;
        left: 362px;
        position: absolute;
        right: 0px;
    }

    .options-box {
        background: #fff;
        border: 1px solid #999;
        border-radius: 3px;
        height: 100%;
        line-height: 35px;
        padding: 10px 10px 30px 10px;
        text-align: left;
        width: 340px;
    }
   </style>
 </head>
 <body>
   <!-- TODO 1: Create a place to put the map in the HTML-->
   <div>
    <div class="container">
        <div class="options-box">
            <h1>Find Your New NYC Home</h1>
            <div>
                <input id="show-listings" type="button" value="Show Listings">
                <input id="hide-listings" type="button" value="Hide Listings">
            </div>
        </div>
    </div>
    <div id="map"></div>
   </div>
   <script>
        var map;
        var markers = [];
        function initMap() {
            // Constructor creates a new map - only center and zoom are required.
            map = new google.maps.Map(document.getElementById('map'), {
                center: {lat: 40.7413549, lng: -73.9980244},
                zoom: 13
            });
            var locations = [
                {title: 'Park Ave Penthouse', location: {lat: 40.7713024, lng: -73.9632393}},
                {title: 'Chelsea Loft', location: {lat: 40.7444883, lng: -73.9949465}},
                {title: 'Union Square Open Floor Plan', location: {lat: 40.7347062, lng: -73.9895759}},
                {title: 'East Village Hip Studio', location: {lat: 40.7281777, lng: -73.984377}},
                {title: 'TriBeCa Artsy Bachelor Pad', location: {lat: 40.7195264, lng: -74.0089934}},
                {title: 'Chinatown Homey Space', location: {lat: 40.7180628, lng: -73.9961237}}
            ];

            var largeInfowindow = new google.maps.InfoWindow();

            for (var i = 0; i < locations.length; i++) {
                var position = locations[i].location;
                var title = locations[i].title;
                var marker = new google.maps.Marker({
                    position: position,
                    title: title,
                    animation: google.maps.Animation.DROP,
                    id: i
                });
                markers.push(marker);
                marker.addListener('click', function() {
                    populateInfoWindow(this, largeInfowindow);
                });
            console.log("I just did code stuff, successfully!");
            }

            document.getElementById('show-listings').addEventListener('click', showListings);
            document.getElementById('hide-listings').addEventListener('click', hidelistings);

            //This function populates the infowindow when the marker is clicked. We'll only allow
            // one inforwindow which will open at the marker that is clicked, and populate based
            // on that marker's position. 
            function populateInfoWindow(marker, infowindow) {
                if (infowindow.marker != marker) {
                    infowindow.marker = marker;
                    infowindow.setContent('<div>' + marker.title + '</div>');
                    infowindow.open(map, marker);
                    //Make sure the marker property is cleared if the window is closed. 
                    infowindow.addListener('closeclick', function(){
                        infowindow.setMarker(null);
                    });
                }
            }
            function showListings() {
                var bounds = new google.maps.LatLngBounds();
                for (var i = 0; i < markers.length; i++) {
                    markers[i].setMap(map);
                    bounds.extend(markers[i].position);
                }
                map.fitBounds(bounds);
            }
            function hidelistings() {
                for (var i = 0; i < markers.length; i++) {
                    markers[i].setMap(null);
                }
            }
        }
     </script>
     <script async defer
        src="https://maps.googleapis.com/maps/api/js?key=DON'T STEAL MY KEY&v=3&callback=initMap">
    </script>
    <script>
        console.log("I just did a map!");
    </script>
 </body>
</html>

3 Answers

Michael, Your question, has to do with one of the most confusing aspects of JavaScript. It is called 'hoisting' which, in my view, really adds to the confusion. Essentially, JavaScript runs your code in two phases. In the first phase variable and function declarations are placed in memory. In the second phase, the 'execution phase,' the code is executed from the variables and functions placed in memory in the first phase. I'd have to see the other code you mention that has to be sequential. There are functions and variables that are not 'hoisted' as they say. If you look up 'hoisting' in JavaScript you should find a more eloquent explanation than I have given here. I hope I at least pointed you in the right direction. Good luck!

Steven Parker
Steven Parker
231,269 Points

This is a mechanism called Hoisting where the system scans the code before beginning execution and handles function and variable declarations in advance. Note that hoisting of functions only occurs with a classic "function" definition, not with "arrow functions". Similarly, only variables declared with "var" are hoisted. Those created with "let" or "const" are not.

Michael Williams
PLUS
Michael Williams
Courses Plus Student 8,059 Points

Thank you both! I've heard of hoisting before, but only as an aside, "The code gets executed through the magic of hoisting..." And that was it.

Hi Michael, glad we could help. Check out JavaScript: Understanding the Weird Parts on Udemy. It goes on sale for $10 all the time or you can watch the first three hours for free on YouTube. It really helped me understand 'hoisting' and other 'weird' things about JavaScript. Good luck, and happy coding!