{"componentChunkName":"component---src-templates-post-js","path":"/blog/are-let-and-const-hoisted","result":{"data":{"markdownRemark":{"html":"<p class=\"intro\">In this post, I will be talking about hoisting, temporal dead zone, and how hoisting works with let and const.</p>\n<h2>What is hoisting?</h2>\n<p>The JavaScript engine before parses the code before executing and during the parsing phase it shifts all the <strong>variable declaration</strong> to the top of the scope. This behavior of the JS engine is called <strong>hoisting</strong>.</p>\n<h3>Variable Hoisting</h3>\n<p>Consider the following code snippet - </p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\">console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>greeting<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// undefined</span>\n\n<span class=\"token keyword\">var</span> greeting <span class=\"token operator\">=</span> <span class=\"token string\">\"Hello\"</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>We can see that the <code class=\"language-text\">greeting</code> variable can be accessed before its declared. This happens because the JS engine modifies our code snippet into something like this - </p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">var</span> greeting<span class=\"token punctuation\">;</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>greeting<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// undefined</span>\n\n<span class=\"token keyword\">var</span> greeting <span class=\"token operator\">=</span> <span class=\"token string\">\"Hello\"</span><span class=\"token punctuation\">;</span></code></pre></div>\n<h3>Function Hoisting</h3>\n<p>The formal function declarations in JavaScript are also hoisted to the top of the scope. For example: </p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token function\">greeting</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// Hello</span>\n\n<span class=\"token keyword\">function</span> <span class=\"token function\">greeting</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Hello\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p><strong>Note:</strong> The important distinction between <strong>variable hoisting</strong> and <strong>function hoisting</strong> is that a <code class=\"language-text\">var</code> variable is hoisted and then auto-initialized to <code class=\"language-text\">undefined</code> whereas a function declaration is hoisted and <strong>initialized to its function value</strong>. </p>\n<h3>Function declaration vs Function expression</h3>\n<p><em>Function hoisting</em> only applies to formal <code class=\"language-text\">function</code> declarations and not to <code class=\"language-text\">function</code> expression assignments. Consider:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token function\">greeting</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// TypeError: greeting is not a function</span>\n\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>greeting<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// undefined</span>\n\n<span class=\"token keyword\">var</span> <span class=\"token function-variable function\">greeting</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">function</span> <span class=\"token function\">greeting</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Hello!\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Above, we can see that the <code class=\"language-text\">greeting</code> variable was hoisted but it was not initialized with the function reference. The engine throws us a <code class=\"language-text\">TypeError: greeting is not a function</code> and not <code class=\"language-text\">ReferenceError: greeting is not defined</code>. The function expression assignments behave very much like <strong>variable hoisting</strong>.</p>\n<h2>What about let and const?</h2>\n<p>So far, I have only talked about <code class=\"language-text\">var</code> and formal <code class=\"language-text\">function</code> declarations. What about the <code class=\"language-text\">let</code> and <code class=\"language-text\">const</code>. Let's see the following code snippet - </p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\">console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>greeting<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// cannot access 'greeting' before initialization</span>\n\n<span class=\"token keyword\">let</span> greeting <span class=\"token operator\">=</span> <span class=\"token string\">\"Hello\"</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>We get a new kind of error, its not a <code class=\"language-text\">ReferenceError</code>, the engine knows about <code class=\"language-text\">greeting</code> but doesn't allow us to use it before its initialized. The JS engine doesn't allow us to access the variables declared with <code class=\"language-text\">let</code> and <code class=\"language-text\">const</code> before they are declared. This is called <strong>Temporal Dead Zone</strong>.</p>\n<p>Let's consider this snippet - </p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">let</span> greeting<span class=\"token punctuation\">;</span>\n\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>greeting<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// undefined</span>\n\ngreeting <span class=\"token operator\">=</span> <span class=\"token string\">\"Hello\"</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Above, we can see that we are able to access the <code class=\"language-text\">greeting</code> variable as soon as it was declared.</p>\n<h2>So, let and const are not hoisted?</h2>\n<p>After seeing the above two code snippets, I was pretty convinced too that <code class=\"language-text\">let</code> and <code class=\"language-text\">const</code> are not hoisted. But they actually are. We can prove this with the help of a few more examples - </p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\">console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">typeof</span> iDontExist<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// undefined</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">typeof</span> greeting<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// cannot access 'greeting' before initialization</span>\n\n<span class=\"token keyword\">let</span> greeting <span class=\"token operator\">=</span> <span class=\"token string\">\"hello\"</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>If the <code class=\"language-text\">greeting</code> variable was not hoisted, we would expect <code class=\"language-text\">typeof greeting</code> to be <code class=\"language-text\">undefined</code> similar to <code class=\"language-text\">typeof iDontExist</code>. This proves that the JS engine knows about our <code class=\"language-text\">greeting</code> variable but still doesn't allow us to access it just yet due to <strong>Temporal Dead Zone</strong>.</p>\n<p>Let's see another example - </p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">let</span> x <span class=\"token operator\">=</span> <span class=\"token string\">'outer value'</span><span class=\"token punctuation\">;</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>x<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// outer value</span>\n\n <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// start TDZ for x</span>\n  console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>x<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// cannot access 'x' before initialization</span>\n  <span class=\"token keyword\">let</span> x <span class=\"token operator\">=</span> <span class=\"token string\">'inner value'</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// declaration ends TDZ for x</span>\n <span class=\"token punctuation\">}</span></code></pre></div>\n<p>Accessing the variable <code class=\"language-text\">x</code> in the inner scope still causes the TDZ error. If the <code class=\"language-text\">let x = &#39;inner value&#39;;</code> was not hoisted then on line 6, it would have logged <code class=\"language-text\">outer value</code>.</p>\n<h2>Conclusion</h2>\n<ul>\n<li>The <code class=\"language-text\">var</code> declarations are hoisted and initialized with <code class=\"language-text\">undefined</code>.</li>\n<li>The formal function declarations are hoisted and initialized with their function reference.</li>\n<li><code class=\"language-text\">let</code> and <code class=\"language-text\">const</code> variables are hoisted too but they cannot be accessed before their declarations. This is called Temporal Dead Zone.</li>\n</ul>","timeToRead":3,"frontmatter":{"title":"Are let and const hoisted?","date":"2020-07-22T00:00:00.000Z","tags":["Javascript"]}}},"pageContext":{"slug":"are-let-and-const-hoisted"}},"staticQueryHashes":["3649515864","63159454"]}