{"id":538,"date":"2018-03-06T07:00:00","date_gmt":"2018-03-06T14:00:00","guid":{"rendered":"https:\/\/coreassistance.com\/tips\/?p=538"},"modified":"2018-02-23T12:34:45","modified_gmt":"2018-02-23T19:34:45","slug":"how-to-avoid-confusing-code-hoisting-surprises","status":"publish","type":"post","link":"https:\/\/coreassistance.com\/tips\/2018\/03\/06\/how-to-avoid-confusing-code-hoisting-surprises\/","title":{"rendered":"How to Avoid Confusing Code Hoisting Surprises"},"content":{"rendered":"<p>JavaScript does some things behind the scenes that you may not expect.  One of these is called <strong>code hoisting<\/strong>, and it can cause some strange issues if you don&#8217;t know what&#8217;s going on behind the scenes.<\/p>\n<p>The way code hoisting works applies to functions and variables a bit differently, so we&#8217;re going to examine each one individually.<\/p>\n<h4>Function Hoisting<\/h4>\n<p>Let&#8217;s start with this example:<\/p>\n<pre><code class=\"javascript\">function sayHello() {\r\n    console.log('Hello!');\r\n}\r\n\r\nsayHello(); \/\/ Hello!<\/code><\/pre>\n<p>That&#8217;s pretty straightforward.  Running this will log <code>Hello!<\/code> to the console.<\/p>\n<p>Let&#8217;s take a look at another version:<\/p>\n<pre><code class=\"javascript\">sayHello(); \/\/ Hello!\r\n\r\nfunction sayHello() {\r\n    console.log('Hello!');\r\n}<\/code><\/pre>\n<p>This code works in exactly the same way as the previous example, but how?  We called the <code>sayHello()<\/code> function before we declared it, so why does this code work?<\/p>\n<p>The answer is that <strong>the function declaration was <em>hoisted<\/em> to the top<\/strong>, effectively making both of these examples work as if they were written like the first example.<\/p>\n<p>Whenever you declare and initialize a function with the <code>function<\/code> keyword, that function is hoisted to the top of the scope where you declared it at runtime.  This allows you to call the function before declaring it.<\/p>\n<p>Here&#8217;s a longer example that will make this clearer.  Examine this code:<\/p>\n<pre><code class=\"javascript\">piggyOne();\r\n\r\nfunction piggyOne() {\r\n    console.log('Straw!');\r\n}\r\n\r\npiggyThree();\r\n\r\nfunction piggyTwo() {\r\n    console.log('Wood!');\r\n}\r\n\r\npiggyTwo();\r\n\r\nfunction piggyThree() {\r\n    console.log('Stone!');\r\n}<\/code><\/pre>\n<p>When this code is run the function declarations will be hoisted, which effectively makes the code run as if it was written like this:<\/p>\n<pre><code class=\"javascript\">function piggyOne() {\r\n    console.log('Straw!');\r\n}\r\n\r\nfunction piggyTwo() {\r\n    console.log('Wood!');\r\n}\r\n\r\nfunction piggyThree() {\r\n    console.log('Stone!');\r\n}\r\n\r\npiggyOne();\r\n\r\npiggyThree();\r\n\r\npiggyTwo();<\/code><\/pre>\n<p>That&#8217;s essentially how function hoisting works.<\/p>\n<h4>Variable Hoisting<\/h4>\n<p>Before we dive in to how variables are hoisted it&#8217;s important to understand the difference between <strong>declaring<\/strong> a variable and <strong>initializing<\/strong> a variable.<\/p>\n<pre><code class=\"javascript\">var theAnswer; \/\/ Declaration\r\ntheAnswer = 42; \/\/ Initialization<\/code><\/pre>\n<p>Declaring a variable is like saying, &#8220;this variable exists,&#8221; whereas initialization is like saying, &#8220;here&#8217;s what this variable contains.&#8221;<\/p>\n<p>You can also declare and initialize a variable at the same time:<\/p>\n<pre><code class=\"javascript\">var theAnswer = 42; \/\/ Declaration & Initialization<\/code><\/pre>\n<p>Now that you know the difference between declaring and initializing a variable, let&#8217;s get back to code hoisting by explaining that <strong>JavaScript hoists variable declarations, but it does <em>not<\/em> hoist variable initializations<\/strong>.<\/p>\n<p>Let&#8217;s look at some examples, starting with this code, which will throw an error:<\/p>\n<pre><code class=\"javascript\">console.log(theAnswer); \/\/ ReferenceError: theAnswer is not defined<\/code><\/pre>\n<p>We didn&#8217;t define <code>theAnswer<\/code>, so that error makes sense.  Now let&#8217;s both define and initialize <code>theAnswer<\/code> before trying to log it:<\/p>\n<pre><code class=\"javascript\">var theAnswer = 42;\r\n\r\nconsole.log(theAnswer); \/\/ 42<\/code><\/pre>\n<p>This example logs <code>42<\/code> to the console, as expected.<\/p>\n<p>Now take a look at this:<\/p>\n<pre><code class=\"javascript\">console.log(theAnswer); \/\/ undefined\r\n\r\nvar theAnswer = 42;<\/code><\/pre>\n<p>This code logs <code>undefined<\/code> to the console, which is an interesting outcome.<\/p>\n<p>Remember, JavaScript only hoists variable declarations, not initializations.  That means the code above effectively executes like this at runtime:<\/p>\n<pre><code class=\"javascript\">var theAnswer; \/\/ Hoisted!\r\n\r\nconsole.log(theAnswer); \/\/ undefined\r\n\r\ntheAnswer = 42;<\/code><\/pre>\n<p><strong>The declaration of the variable was hoisted, but the initialization was not.<\/strong>  JavaScript is essentially tearing the single line of code that declared and initialized <code>theAnswer<\/code> in half, and putting the declaration at the top.  This prevents the <code>console.log()<\/code> line from throwing an error, but it because <code>theAnswer<\/code> hasn&#8217;t been initialized yet, the value inside is <code>undefined<\/code>.<\/p>\n<h4>What About Variables Containing Functions?<\/h4>\n<p>You might be wondering how code hoisting works in a scenario like this:<\/p>\n<pre><code class=\"javascript\">sayHello();\r\n\r\nvar sayHello = function() {\r\n    console.log('Hello!');\r\n}<\/code><\/pre>\n<p>This code will actually throw an error: <code>TypeError: sayHello is not a function<\/code>.  That&#8217;s because, in this case, <code>sayHello<\/code> is being declared as a variable with the <code>var<\/code> keyword, so only that variable declaration is hoisted to the top, effectively making the code run like this:<\/p>\n<pre><code class=\"javascript\">var sayHello; \/\/ Hoisted!\r\n\r\nsayHello(); \/\/ TypeError: sayHello is not a function (execution stops here)\r\n\r\nsayHello = function() {\r\n    console.log('Hello!');\r\n}<\/code><\/pre>\n<p>One thing to note is that JavaScript isn&#8217;t actually rewriting your code when it hoists function and variable declarations to the top.  What&#8217;s going on behind the scenes is a bit complicated, and has to do with JavaScript putting function and variable declarations in memory during the compile phase.  The good news is that you don&#8217;t need to know the technical specifics of code hoisting to understand how it works and the impact it has on your code.<\/p>\n<p>Now that you know how code hoisting works I recommend you work with it instead of against it.  That is, <strong>declare your functions and variables first<\/strong>.  JavaScript is going to do so anyway, and if your code matches what&#8217;s actually going on behind the scenes it will be easier to manage and debug, with fewer surprises.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Code hoisting in JavaScript can cause some strange and unexpected behavior if you don&#8217;t know what&#8217;s going on behind the scenes.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[],"class_list":["post-538","post","type-post","status-publish","format-standard","hentry","category-javascript"],"_links":{"self":[{"href":"https:\/\/coreassistance.com\/tips\/wp-json\/wp\/v2\/posts\/538","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/coreassistance.com\/tips\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/coreassistance.com\/tips\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/coreassistance.com\/tips\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/coreassistance.com\/tips\/wp-json\/wp\/v2\/comments?post=538"}],"version-history":[{"count":23,"href":"https:\/\/coreassistance.com\/tips\/wp-json\/wp\/v2\/posts\/538\/revisions"}],"predecessor-version":[{"id":649,"href":"https:\/\/coreassistance.com\/tips\/wp-json\/wp\/v2\/posts\/538\/revisions\/649"}],"wp:attachment":[{"href":"https:\/\/coreassistance.com\/tips\/wp-json\/wp\/v2\/media?parent=538"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/coreassistance.com\/tips\/wp-json\/wp\/v2\/categories?post=538"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/coreassistance.com\/tips\/wp-json\/wp\/v2\/tags?post=538"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}