{"id":697,"date":"2011-12-22T16:21:49","date_gmt":"2011-12-22T14:21:49","guid":{"rendered":"http:\/\/mclightning.com\/?p=697"},"modified":"2011-12-22T16:21:49","modified_gmt":"2011-12-22T14:21:49","slug":"javascript-closures","status":"publish","type":"post","link":"https:\/\/maximusabrams.com\/?p=697","title":{"rendered":"Javascript Closures : My Journey with Object-Oriented JavaScript and the Power of Closures"},"content":{"rendered":"<p>Over the past year, I&#8217;ve been deeply immersed in developing a web application project. About seven months ago, as the complexity of the project grew, I made the switch to object-oriented JavaScript. This shift was transformative, drastically improving my productivity in ways that are hard to describe\u2014you truly have to experience it to understand its impact.<\/p>\n<h3>Discovering the Power of Closures<\/h3>\n<p>As I delved into object-oriented JavaScript, I encountered several advanced concepts that I hadn&#8217;t previously needed or explored. One of the most significant among these was closures. While I wouldn\u2019t yet consider myself an expert in JavaScript or its closures, I\u2019ve gained valuable insights that I\u2019d like to share.<\/p>\n<p>In JavaScript, a closure is a function that &#8220;remembers&#8221; the environment in which it was created, even after that environment no longer exists. This means that a closure can retain access to variables from its surrounding scope, even after the outer function has finished executing.<\/p>\n<h3>When Do Closures Become Useful?<\/h3>\n<p>Closures become particularly useful when working with jQuery in conjunction with object-oriented JavaScript. Here\u2019s an example to illustrate:<\/p>\n<div class=\"dark bg-gray-950 contain-inline-size rounded-md border-[0.5px] border-token-border-medium\">\n<div class=\"flex items-center relative text-token-text-secondary bg-token-main-surface-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md\">javascript<\/p>\n<div class=\"flex items-center\"><span class=\"\" data-state=\"closed\"><button class=\"flex gap-1 items-center\">Copy code<\/button><\/span><\/div>\n<\/div>\n<div class=\"overflow-y-auto p-4\" dir=\"ltr\"><code class=\"!whitespace-pre hljs language-javascript\">$(<span class=\"hljs-string\">'li'<\/span>).<span class=\"hljs-title function_\">each<\/span>(<span class=\"hljs-keyword\">function<\/span>() {<br \/>\n    $(<span class=\"hljs-variable language_\">this<\/span>).<span class=\"hljs-title function_\">html<\/span>(<span class=\"hljs-variable language_\">this<\/span>.<span class=\"hljs-property\">counter<\/span>);<br \/>\n});<br \/>\n<\/code><\/div>\n<\/div>\n<p>At first glance, this code might seem correct, but it doesn&#8217;t work as expected. The issue arises because the <code>this<\/code> keyword inside the <code>each()<\/code> function refers to the current <code>$('li')<\/code> element, not to the object that contains the <code>counter<\/code> property.<\/p>\n<h3>The Solution: Using Closures<\/h3>\n<p>A common but flawed solution might be:<\/p>\n<div class=\"dark bg-gray-950 contain-inline-size rounded-md border-[0.5px] border-token-border-medium\">\n<div class=\"flex items-center relative text-token-text-secondary bg-token-main-surface-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md\">javascript<\/p>\n<div class=\"flex items-center\"><span class=\"\" data-state=\"closed\"><button class=\"flex gap-1 items-center\">Copy code<\/button><\/span><\/div>\n<\/div>\n<div class=\"overflow-y-auto p-4\" dir=\"ltr\"><code class=\"!whitespace-pre hljs language-javascript\">$(<span class=\"hljs-variable language_\">this<\/span>).<span class=\"hljs-title function_\">html<\/span>(obj.<span class=\"hljs-property\">counter<\/span>);<br \/>\n<\/code><\/div>\n<\/div>\n<p>However, this approach assumes that the object is always named <code>obj<\/code>, which violates the principles of object-oriented programming. Moreover, it makes it impossible to create and use multiple instances of the class within the same document. While a workaround could involve using separate documents and displaying them within <code>iframe<\/code> elements, this is hardly a professional or scalable solution.<\/p>\n<p>Here\u2019s where JavaScript closures come to the rescue. By using a closure, we can pass the correct reference to the object (<code>this<\/code>) into the <code>each()<\/code> function in jQuery. This ensures that the code behaves as expected, even with multiple instances of the class:<\/p>\n<div class=\"dark bg-gray-950 contain-inline-size rounded-md border-[0.5px] border-token-border-medium\">\n<div class=\"flex items-center relative text-token-text-secondary bg-token-main-surface-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md\">javascript<\/p>\n<div class=\"flex items-center\"><span class=\"\" data-state=\"closed\"><button class=\"flex gap-1 items-center\">Copy code<\/button><\/span><\/div>\n<\/div>\n<div class=\"overflow-y-auto p-4\" dir=\"ltr\"><code class=\"!whitespace-pre hljs language-javascript\"><span class=\"hljs-keyword\">const<\/span> self = <span class=\"hljs-variable language_\">this<\/span>;<br \/>\n$(<span class=\"hljs-string\">'li'<\/span>).<span class=\"hljs-title function_\">each<\/span>(<span class=\"hljs-keyword\">function<\/span>() {<br \/>\n    $(<span class=\"hljs-variable language_\">this<\/span>).<span class=\"hljs-title function_\">html<\/span>(self.<span class=\"hljs-property\">counter<\/span>);<br \/>\n});<br \/>\n<\/code><\/div>\n<\/div>\n<p>This approach preserves the object-oriented design while allowing for flexibility and scalability.<\/p>\n<h3>Modern Alternative: Arrow Functions<\/h3>\n<p>In modern JavaScript, arrow functions offer a more elegant solution. Arrow functions don\u2019t have their own <code>this<\/code> context; instead, they inherit <code>this<\/code> from the surrounding lexical scope, which can simplify the code:<\/p>\n<div class=\"dark bg-gray-950 contain-inline-size rounded-md border-[0.5px] border-token-border-medium\">\n<div class=\"flex items-center relative text-token-text-secondary bg-token-main-surface-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md\">javascript<\/p>\n<div class=\"flex items-center\"><span class=\"\" data-state=\"closed\"><button class=\"flex gap-1 items-center\">Copy code<\/button><\/span><\/div>\n<\/div>\n<div class=\"overflow-y-auto p-4\" dir=\"ltr\"><code class=\"!whitespace-pre hljs language-javascript\">$(<span class=\"hljs-string\">'li'<\/span>).<span class=\"hljs-title function_\">each<\/span>(<span class=\"hljs-function\">() =&gt;<\/span> {<br \/>\n    $(<span class=\"hljs-variable language_\">this<\/span>).<span class=\"hljs-title function_\">html<\/span>(<span class=\"hljs-variable language_\">this<\/span>.<span class=\"hljs-property\">counter<\/span>);<br \/>\n});<br \/>\n<\/code><\/div>\n<\/div>\n<p>This approach removes the need for the <code>self = this<\/code> workaround and adheres to the principles of object-oriented programming.<\/p>\n<h3>A Note on jQuery Functions<\/h3>\n<p>It\u2019s worth mentioning that some jQuery functions, such as <code>.bind()<\/code>, allow you to pass arguments and explicitly set the <code>this<\/code> context. However, <code>.bind()<\/code> is typically used for attaching event handlers rather than iterating over elements like <code>.each()<\/code>. Arrow functions often provide a more straightforward solution in these scenarios.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Over the past year, I&#8217;ve been deeply immersed in developing a web application project. About seven months ago, as the complexity of the project grew, I made the switch to object-oriented JavaScript. This shift was transformative, drastically improving my productivity in ways that are hard to describe\u2014you truly have to experience it to understand its [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[8,1,9],"tags":[65,140,156,159,215,219,227],"class_list":["post-697","post","type-post","status-publish","format-standard","hentry","category-programming-2","category-uncategorized","category-web","tag-closure","tag-html5","tag-javascript-2","tag-jquery","tag-object","tag-oop","tag-oriented"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/maximusabrams.com\/index.php?rest_route=\/wp\/v2\/posts\/697","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/maximusabrams.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/maximusabrams.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/maximusabrams.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/maximusabrams.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=697"}],"version-history":[{"count":0,"href":"https:\/\/maximusabrams.com\/index.php?rest_route=\/wp\/v2\/posts\/697\/revisions"}],"wp:attachment":[{"href":"https:\/\/maximusabrams.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=697"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/maximusabrams.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=697"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/maximusabrams.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=697"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}