Joe Zim's JavaScript Blog

http://www.joezimjs.com/javascript/javascript-closures-and-the-module-pattern/

Search

Main menu

Skip to primary content
Skip to secondary content
  • Home
  • JavaScript
  • News
  • Projects
  • About Me
  • Contact Me

Post navigation

← Previous Next→

JavaScript Closures and the Module Pattern

Posted on April 30, 2012

One of the most widely used design patterns in JavaScript is the module pattern.  The module pattern makes use of one of the nicer features of JavaScript – closures – in order to give you some control of the privacy of your methods so that third party applications cannot access private data or overwrite it. In this post I’ll teach you what a closure is, how it works, and how to utilize it to implement the module pattern in your own JavaScript code.

What is a Closure?

Closures are a construct of the JavaScript language. Within JavaScript all variables are accessible from the global scope except variables that are declared within a function using the var keyword.

  1. variable1 = 1; // Global Scope
  2. var variable2 = 2; // Not within a function: Global Scope
  3.  
  4. function funcName() {
  5.     variable3 = 3; // No var keyword: Global Scope
  6.     var variable4 = 4; // Local Scope only
  7. }

Within a function, you also have access to the global scope and every other scope above the function that you are in. In other words an inner function has access to the variables that are within the function that wraps it.

  1. var globalvar = 1; // Global Scope
  2.  
  3. function outer() {
  4.     var outervar = 2; // Scope is within outer()
  5.    
  6.     function inner() {
  7.         var innervar = 3; // Scope is within inner()
  8.         console.log(globalvar); // => 1
  9.         console.log(outervar); // => 2
  10.         console.log(innervar); // => 3
  11.     }
  12.    
  13.     console.log(globalvar); // => 1
  14.     console.log(outervar); // => 2
  15.     console.log(innervar); // => Reference Error;
  16. }
  17.  
  18. console.log(globalvar); // => 1
  19. console.log(outervar); // => Reference Error
  20. console.log(innervar); // => Reference Error

Every real JavaScript programmer should know this if he or she wants to become great. Knowing this, you can come to the conclusion that there is a way to keep all of your code outside of the global namespace and you would be correct. This is especially helpful when you don’t want to give anyone a chance to override any of your code without your permission. You can accomplish this by using an anonymous function (no name is given to it and it is not assigned to a variable) that immediately executes itself. This is commonly known as a Self-Invoking Anonymous Function (SIAF), though it is probably more accurately referred to as anImmediately Invoked Function Expression (IIFE – pronounced “iffy”) by Ben Alman.

  1. (function() {
  2.     // This function immediately runs and all variables within here are private
  3. }());

Right after the closing curly brace, just put an opening and closing parenthesis and the function will immediately be executed. The parentheses around the entire function expression aren’t necessary for the code to run, but are generally used as a signal to other developers that this is an IIFE, not a standard function. Some people like to prefix with an exclamation point (!) or a semicolon (;), rather than wrapping the whole thing in parentheses.

Using Closures for the Module Pattern

Knowing what we know about closures, we can create objects using the module pattern.  By returning an object or variable and assigning it to a variable outside of the function, we can expose whatever we wish to the outside world, so we can have both public and private methods.

  1. var Module = (function() {
  2.     // Following function is private, but can be accessed by the public functions
  3.     function privateFunc() { … };
  4.    
  5.     // Return an object that is assigned to Module
  6.     return {
  7.         publicFunc: function() {
  8.             privateFunc(); // publicFunc has direct access to privateFunc
  9.         }
  10.     };
  11. }());

That’s essentially the module pattern right there.  You can also use the arguments to send in and shrink the name of commonly used assets:

  1. var Module = (function($, w, undefined) {
  2.     // …
  3.     // return {…};
  4. }(jQuery, window));

I sent in jQuery and window, which were abbreviated to $ and w, respectively. Notice that I didn’t send anything in for the third argument. This way undefined will be undefined, so it works perfectly. Some people do this with undefined because for whatever reason it is editable. So if you check to see if something is undefined, but undefined has been changed, your comparison will not work. This technique ensures that it will work as expected.

The Revealing Module Pattern

The revealing module pattern is another way to write the module pattern that takes a bit more code, but is easier to understand and read sometimes. Instead of defining all of the private methods inside the IIFE and the public methods within the returned object, you write all methods within the IIFE and just “reveal” which ones you wish to make public within the return statement.

  1. var Module = (function() {
  2.     // All functions now have direct access to each other
  3.     var privateFunc = function() {
  4.         publicFunc1();
  5.     };
  6.    
  7.     var publicFunc1 = function() {
  8.         publicFunc2();
  9.     };
  10.    
  11.     var publicFunc2 = function() {
  12.         privateFunc();
  13.     };
  14.    
  15.     // Return the object that is assigned to Module
  16.     return {
  17.         publicFunc1: publicFunc1,
  18.         publicFunc2: publicFunc2
  19.     };
  20. }());

There are a few advantages to the revealing module pattern versus the normal module pattern:

  1. All the functions are declared and implemented in the same place, thus creating less confusion.
  2. Private functions now have access to public functions if they need to.
  3. When a public function needs to call another public function they can callpublicFunc2() rather thanthis.publicFunc2(), which saves a few characters and saves your butt if thisends up being something different than originally intended.

The only real downside to the revealing module pattern, as I said, is that you have to write a bit more code because you have to write the function and then write its name again in the return statement, though it could end up saving you code because you can skip the this. part.

Module Pattern for Extension

The last thing I wanted to talk about was using the module pattern for extending already-existing modules. This is done quite often when making plugins to libraries like jQuery, as you can see below.

  1. var jQuery = (function($) {
  2.     $.pluginFunc = function() {
  3.         …
  4.     }
  5.    
  6.     return $;    
  7. }(jQuery));

This code is pretty flexible because you don’t even need the var jQuery = or the returnstatement near the end. jQuery will still be extended with the new method without them. It’s actually probably bad for performance to return the entire jQuery object and assign it, however, if you want to assign jQuery to a new variable name at the same time that you’re extending it, you can just change jQuery on the first line to whatever you want.

A Foregone Conclusion

That’s all there is for today, friend. These are common techniques and features, so even if you don’t make use of the knowledge from this post, keep it in the back of your mind just in case it comes up (which it probably will). Also, make sure to stop in again on Thursday to read about requestAnimationFrame: a new API coming out in browsers to make animations smoother and cleaner. Finally, don’t forget to share and comment below. Thanks and Happy Coding!

  • Post to Facebook
  • Post to Twitter
  • Post to Pinterest
  • Add to LinkedIn
    7
    7
    7
    7
    7
    7
    7
    7
    7

  • Add to Reddit
  • Add to DZone
  • Post to StumbleUpon
  • Post to Delicious
    9
    9
    9
    9
    9
    9
    9
    9
    9

  • Post to Plurk

Related posts:

  1. JavaScript Design Patterns: Command
  2. JavaScript Design Patterns: Observer
  3. JavaScript Design Patterns: Singleton
  4. JavaScript Design Patterns: Adapter
  5. JavaScript Design Patterns: Factory

This entry was posted in JavaScript and tagged design patterns, how to, javascript, plugin, security byJoseph Zimmerman. Bookmark the permalink.

  • Disqus
  • Like
  • Dislike
    • liked this.
Login

Add New Comment

  • Post as …

                        Sort by popular now                                Sort by best rating                                Sort by newest first                                Sort by oldest first                  

Showing 4 comments

  • infocyde

    Thanks for sharing this, I think I have a better grasp of closures now.

     
    • Like
    • Reply
    • 2 days ago
     

  • Joe Zimmerman

    You think you do? Well, if you have any questions, feel free to contact me via the form on this site or FB/Twitter/G+. Any of those will work. You can find links to my social profiles in the footer (or at the top of the sidebar if you happen to be on a page that shows the sidebar.

     
    • Like
    • Reply
    • 2 days ago
    • in reply to infocyde
     

  • Robin

    Your second code example is either confusing or incorrect:

    console.log(outer) does not produce undefined, it will log the outer function itself.
    console.log(innter) does not produce undefined, it will cause a ReferenceError which if uncaught is fatal.

    There is a big difference between a variable being undefined and a variable not existing at all.

    For example:
    var iExist;
    console.log(iExist) => undefined

    console.log(iDontExist) => ReferenceError

     
    • Like
    • Reply
    • 3 days ago
     

  • Joe Zimmerman

    You're quite correct. Sorry about the confusion. 1st off I wasn't thinking, so I named the variables the same as the functions that they were within, so I now changed them to have a "var" suffix. Also I went back and changed the comments from saying "undefined" to ReferenceError. Thanks for catching that.

     
    • Like
    • Reply
    • 3 days ago
    • in reply to Robin
     

  • Subscribe by email
  • RSS

 

MAIN MENU

  • Home
  • JavaScript
  • News
  • Projects
  • About Me
  • Contact Me
 

MEET THE AUTHOR

I started web development in 8th grade and I've been stuck with the sickness ever since. Now I'm attempting to infect the world with the same sickness via this blog. Read more About Me.

    

NEWSLETTER SIGNUP

Receive a coupon for $5 off "Getting Good With JavaScript" when you sign up for the newsletter!

Name:
Email:

 

转载于:https://www.cnblogs.com/MyFlora/archive/2012/05/04/2482621.html

javascript闭包新认识相关推荐

  1. JavaScript闭包如何工作?

    您将如何向了解其闭包概念(例如函数,变量等)的人解释JavaScript闭包,但却不了解闭包本身? 我已经在Wikipedia上看到了Scheme示例 ,但是不幸的是它没有帮助. #1楼 我知道已经有 ...

  2. [转载]深入理解JavaScript闭包(closure)

    最近在网上查阅了不少Javascript闭包(closure)相关的资料,写的大多是非常的学术和专业.对于初学者来说别说理解闭包了,就连文字叙述都很难看懂.撰写此文的目的就是用最通俗的文字揭开Java ...

  3. [转]Javascript 闭包

    [转]Javascript 闭包 简介 Closure 所谓"闭包",指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分. 闭 ...

  4. 深入浅出Javascript闭包

    深入浅出Javascript闭包 一.引子 闭包(closure)是 JavaScript 语言的一个难点,面试时常被问及,也是它的特色,很多高级应用都要依靠闭包实现.本文尽可能用简单易懂的话,讲清楚 ...

  5. JavaScript闭包的底层运行机制

    转自:http://blog.leapoahead.com/2015/09/15/js-closure/ 我研究JavaScript闭包(closure)已经有一段时间了.我之前只是学会了如何使用它们 ...

  6. 深入理解JavaScript闭包(closure) 【收藏】

    深入理解JavaScript闭包(closure) 原文地址:http://www.felixwoo.com/archives/247  Felix Woo 最近在网上查阅了不少Javascript闭 ...

  7. 好程序员技术文档HTML5开发中的javascript闭包

    好程序员技术文档HTML5开发中的javascript闭包,事实上,通过使用闭包,我们可以做很多事情.比如模拟面向对象的代码风格;更优雅,更简洁的表达出代码;在某些方面提升代码的执行效率,同时避免对命 ...

  8. javascript闭包_JavaScript闭包教程–带有JS闭包示例代码

    javascript闭包 Closures – many of you JavaScript devs have probably heard this term before. When I sta ...

  9. 【转】深入理解JavaScript闭包(closure)

    文章来源:http://www.felixwoo.com/archives/247 最近在网上查阅了不少Javascript闭包(closure)相关的资料,写的大多是非常的学术和专业.对于初学者来说 ...

最新文章

  1. 5g理论速度_5G时代手机基带厂商实力比拼
  2. 大数据集群启停shell脚本:hadoop(hdfs、yarn)、hbase集群启停
  3. 用servlet校验密码2
  4. 第一个JSP文件的创建过程
  5. Python XML操作处理
  6. 将要发布的开源CCOA的照片一览
  7. 【SCOI2005】【BZOJ1083】繁忙的都市(MST模板)
  8. 搭建云上博客——阿里云实验室 学习笔记
  9. 试验设计与因果分析感想
  10. 微信公众号开发者模式入门
  11. 小学生计算机课上的小游戏,信息技术教师必备:适合小学生玩的游戏
  12. D-028 DDR3硬件电路设计
  13. 史上最全超级金融知识(珍藏版)
  14. iOS 打包上传蒲公英和AppStore出问题
  15. 信用风险计量模型汇总
  16. 用devc++表白_【理工大表白墙】19级倪yl,风吹起如花般破碎的流年,而你的笑容摇晃摇晃,成为我命途中最美的点缀...
  17. Java 中 throw 和 throws 联系与区别
  18. Python程序的执行过程 解释型语言和编译型语言
  19. 搞懂这 10 张脑图后,我膨胀了。
  20. 嵌入式分享合集121

热门文章

  1. php怎么防止爬虫,PHP语言学习之php 防止爬虫设置
  2. Python-Matplotlib可视化(4)——添加注释让统计图通俗易懂
  3. c++中的队列_C ++中的队列
  4. Android ListView示例教程
  5. CS229学习笔记(3)逻辑回归(Logistic Regression)
  6. web前端基础面试题
  7. 简单的shell命令
  8. Spark分区详解!DT大数据梦工厂王家林老师亲自讲解!
  9. linux下如何关闭防火墙、查看当前的状态、开放端口
  10. MySQL常见故障处理手册_转