{"id":3526,"date":"2021-12-20T13:16:11","date_gmt":"2021-12-20T07:46:11","guid":{"rendered":"https:\/\/blog.osmosys.co\/?p=3526"},"modified":"2024-02-02T04:57:08","modified_gmt":"2024-02-02T04:57:08","slug":"lexical-environment-closure","status":"publish","type":"post","link":"https:\/\/staging.osmosys.co\/uk\/lexical-environment-closure\/","title":{"rendered":"Lexical Environment &amp; Closure"},"content":{"rendered":"<div id=\"bsf_rt_marker\"><\/div>\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_82_1 counter-hierarchy ez-toc-counter ez-toc-white ez-toc-container-direction\">\r\n<div class=\"ez-toc-title-container\">\r\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\r\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Toggle Table of Content\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\r\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/staging.osmosys.co\/uk\/lexical-environment-closure\/#Code_Blocks\" >Code Blocks<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/staging.osmosys.co\/uk\/lexical-environment-closure\/#Nested_Functions\" >Nested Functions<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/staging.osmosys.co\/uk\/lexical-environment-closure\/#Lexical_Environment\" >Lexical Environment<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/staging.osmosys.co\/uk\/lexical-environment-closure\/#Closure\" >Closure<\/a><\/li><\/ul><\/nav><\/div>\r\n<h2 class=\"wp-block-heading\" id=\"bkmrk-introduction\"><span class=\"ez-toc-section\" id=\"Code_Blocks\"><\/span><strong><span style=\"color: #c20404\">Code Blocks<br><\/span><\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>If a variable is declared inside a code block<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">{...}<\/pre>\n\n\n\n<p>it&#8217;s only visible inside that block.<\/p>\n\n\n\n<p>For example:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">{\n  let message = \"Hello\";\n  alert(message);\n}\nalert(message);<\/pre>\n\n\n\n<p>We can use this to isolate a piece of code that does its own task, with variables that only belong to it:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">{\n  let message = \"Hello\";\n  alert(message);\n}\n\n{\n  let message = \"Goodbye\";\n  alert(message);\n}<\/pre>\n\n\n\n<p>For if, for, while and so on, variables declared in {\u2026} are also only visible inside:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">if (true) {\n  let phrase = \"Hello!\";\n\n  alert(phrase); \/\/ Hello!\n}\n\nalert(phrase); \/\/ Error, no such variable!<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"bkmrk-introduction\"><span class=\"ez-toc-section\" id=\"Nested_Functions\"><\/span><strong><span style=\"color: #c20404\">Nested Functions<br><\/span><\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>A function is called&#8221;nested&#8221; when it is created inside another function. It is easily possible to do this with JavaScript. We can use it to organize our code, like this:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">function sayHiBye(firstName, lastName) {\n\n  \/\/ helper nested function to use below\n  function getFullName() {\n    return firstName + \" \" + lastName;\n  }\n\n  alert( \"Hello, \" + getFullName() );\n  alert( \"Bye, \" + getFullName() );\n\n}<\/pre>\n\n\n\n<pre class=\"wp-block-preformatted\">\nHere the nested function getFullName()\u00a0is made for convenience. It can access the outer variables and so can return the full name. Nested functions are quite common in JavaScript.<\/pre>\n\n\n\n<p>What&#8217;s much more interesting, a nested function can be returned: either as a property of a new object or as a result by itself. It can then be used somewhere else. No matter where, it still has access to the same outer variables.<\/p>\n\n\n\n<p>Below, makeCounter creates the &#8220;counter&#8221; function that returns the next number on each invocation:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">function makeCounter() {\n  let count = 0;\n\n  return function() {\n    return count++;\n  };\n}\n\n\nlet counter = makeCounter();\nalert( counter() ); \/\/ 0\nalert( counter() ); \/\/ 1\nalert( counter() ); \/\/ 2<\/pre>\n\n\n\n<pre class=\"wp-block-preformatted\">\nDespite being simple, slightly modified variants of that code have practical uses, for instance, as a random number generator to generate random values for automated tests.\nHow does this work? If we create multiple counters, will they be independent? What's going on with the variables here?\nUnderstanding such things is great for the overall knowledge of JavaScript and beneficial for more complex scenarios. So let's go a bit in-depth<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"bkmrk-introduction\"><span class=\"ez-toc-section\" id=\"Lexical_Environment\"><\/span><strong><span style=\"color: #c20404\">Lexical Environment<\/span><\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Every execution context has a reference to its outer environment, and that outer environment is called Lexical Environment.<\/p>\n\n\n\n<p>We can say that whenever an execution context is created to execute the code along with it a lexical environment is also created by the JavaScript engine. Each lexical environment has reference to its parent lexical environments.<\/p>\n\n\n\n<p>A lexical environment can be considered as a data structure which holds <b>identifier-variable mapping <\/b>(identifier =&gt; name of the variable\/functions). It has two components:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><b> Environment Record &#8211; <\/b>Actual place where the variable and function declarations are stored<\/li>\n\n\n\n<li><b>Reference To Outer Environment &#8211; <\/b>it has access to its outer (parent) lexical environment. This component is the most important in order to understand how closures work.<\/li>\n<\/ol>\n\n\n\n<p>A lexical environment object looks like this:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">lexicalEnvironment = { \nenvironmentRecord: { \n&lt;identifier&gt; : &lt;value&gt;, \n&lt;identifier&gt; : &lt;value&gt; \n} \nouter: &lt; Reference to the parent lexical environment&gt; \n}<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Closure\"><\/span><strong><span style=\"color: #c20404\">Closure<\/span><\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>A closure is a function that remembers its outer variables and can access them. In some languages, that&#8217;s not possible, or a function should be written in a special way to make it happen. But as explained above, in JavaScript, all functions are naturally closures (there is only one exception, to be covered in The &#8220;new Function&#8221; syntax).<\/p>\n\n\n\n<p>Usually, a function remembers where it was born in the special property [[Environment]]. It references the Lexical Environment from where it&#8217;s created (we covered that in the chapter Variable scope, closure).<\/p>\n\n\n\n<p>But when a function is created using new keyword, its [[Environment]] is set to reference not the current Lexical Environment, but the global one.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">function getFunc() {\n  let value = \"test\";\n  let func = new Function('alert(value)');\n  return func;\n}\n\ngetFunc()(); \/\/ error: value is not defined\n\nfunction person() {\n    let name = 'Peter';\n    return function displayName() {\n        console.log(name);\n    };\n}\nlet peter = person();\npeter(); \/\/ prints 'Peter'<\/pre>\n\n\n\n<p>When person()&nbsp; is executed, the JavaScript engine creates a new execution context and a lexical environment for the function. After this function finishes, it returns displayName() and assigns it to peter variable.When the person()\u0393\u00f6\u00bc\u251c\u00ed finishes, its execution context is removed from the stack. But its lexical environment is still in the memory because its lexical environment is referenced by the lexical environment of displayName() . So name variable is still accessible.<\/p>\n\n\n\n<p><strong><span style=\"color: #c20404\">Posted By:<\/span> <span style=\"color: #000080\">Shubham Kumar Jha, Osmosee<\/span><\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Code Blocks If a variable is declared inside a code block it&#8217;s only visible inside that block. For example: We can use this to isolate a piece of code that does its own task, with variables that only belong to it: For if, for, while and so on, variables declared in {\u2026} are also only [&hellip;]<\/p>\n","protected":false},"author":11,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_et_pb_use_builder":"","_et_pb_old_content":"","_et_gb_content_width":"","_lmt_disableupdate":"","_lmt_disable":"","jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[39],"tags":[],"class_list":["post-3526","post","type-post","status-publish","format-standard","hentry","category-general"],"modified_by":null,"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/staging.osmosys.co\/uk\/wp-json\/wp\/v2\/posts\/3526","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/staging.osmosys.co\/uk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/staging.osmosys.co\/uk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/staging.osmosys.co\/uk\/wp-json\/wp\/v2\/users\/11"}],"replies":[{"embeddable":true,"href":"https:\/\/staging.osmosys.co\/uk\/wp-json\/wp\/v2\/comments?post=3526"}],"version-history":[{"count":0,"href":"https:\/\/staging.osmosys.co\/uk\/wp-json\/wp\/v2\/posts\/3526\/revisions"}],"wp:attachment":[{"href":"https:\/\/staging.osmosys.co\/uk\/wp-json\/wp\/v2\/media?parent=3526"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/staging.osmosys.co\/uk\/wp-json\/wp\/v2\/categories?post=3526"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/staging.osmosys.co\/uk\/wp-json\/wp\/v2\/tags?post=3526"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}