├── module ├── export.js ├── import.js ├── module.js ├── module.md └── revealing.js ├── namespacing ├── automated_nesting.js ├── iife.js ├── injection.js ├── namespacing.md ├── nested.js ├── object_literal.js ├── prefix.js └── single_global_variable.js └── readme.md /module/export.js: -------------------------------------------------------------------------------- 1 | 2 | var myModule = (function() { 3 | var module = {}; 4 | var privateVar = "bar"; 5 | 6 | var privateMethod = function() { 7 | console.log(privateVar); 8 | } 9 | var privateMethod2 = function() { 10 | return Math.random(2); 11 | } 12 | module.publicMethod = privateMethod; 13 | module.publicVar = privateMethod2(); 14 | 15 | return module; 16 | }()); 17 | -------------------------------------------------------------------------------- /module/import.js: -------------------------------------------------------------------------------- 1 | /* 2 | This variation of the pattern demonstrates how globals (e.g jQuery, Underscore) can be passed in as arguments to our module's anonymous function. This effectively allows us to import them and locally alias them as we wish. 3 | */ 4 | 5 | var myModule = (function(SweetQuery, SweetUnderscore) { 6 | var privateMethod = function(todo) { 7 | SweetQuery('.todos').append(todo); 8 | } 9 | var privateMethod2 = function(array){ 10 | console.log( SweetUnderscore.min(array) ); 11 | } 12 | 13 | return { 14 | addTodo: function(todo) { 15 | privateMethod(todo); 16 | }, 17 | minArray: function(array) { 18 | privateMethod2(array); 19 | } 20 | } 21 | // import jQuery and Underscore 22 | }(jQuery, _)); 23 | -------------------------------------------------------------------------------- /module/module.js: -------------------------------------------------------------------------------- 1 | var cartModule = (function () { 2 | // privates 3 | var cart = []; 4 | 5 | function removeItem(index) { 6 | cart.pop(index) 7 | } 8 | 9 | // Return an object exposed to the public 10 | return { 11 | addItem: function(item) { 12 | cart.push(item); 13 | }, 14 | 15 | getItemCount: function () { 16 | return cart.length; 17 | }, 18 | 19 | // Public alias to a private function 20 | removeItem: removeItem, 21 | 22 | getTotal: function () { 23 | var count = this.getItemCount(), 24 | price = 0; 25 | while (count--) { 26 | price += cart[count].price; 27 | } 28 | return price; 29 | } 30 | }; 31 | }()); 32 | -------------------------------------------------------------------------------- /module/module.md: -------------------------------------------------------------------------------- 1 | The Module pattern was originally defined as a way to provide both private and public encapsulation for classes in conventional software engineering. 2 | In JavaScript, the Module pattern is used to further emulate the concept of classes in such a way that we're able to include both public/private methods and variables inside a single object, thus shielding particular parts from the global scope. What this results in is a reduction in the likelihood of our function names conflicting with other functions defined in additional scripts on the page. 3 | -------------------------------------------------------------------------------- /module/revealing.js: -------------------------------------------------------------------------------- 1 | /* 2 | simply define all of our functions and variables in the private scope and return an anonymous object with pointers to the private functionality we wished to reveal as public. 3 | */ 4 | 5 | var cartModule = (function () { 6 | // privates 7 | var cart = []; 8 | 9 | function removeItem(index) { 10 | cart.pop(index) 11 | } 12 | function getItemCount() { 13 | return cart.length; 14 | } 15 | function addItem(item) { 16 | cart.push(item); 17 | } 18 | function getTotal() { 19 | var count = this.getItemCount(), 20 | price = 0; 21 | while (count--) { 22 | price += cart[count].price; 23 | } 24 | return price; 25 | } 26 | 27 | // Return an object exposed to the public 28 | return { 29 | addItem: addItem, 30 | getItemCount: getItemCount, 31 | removeItem: removeItem, 32 | getTotal: getTotal 33 | }; 34 | }()); 35 | 36 | /* 37 | Disadvantage: 38 | A disadvantage of this pattern is that if a public function refers to a private function, that public function can't be overridden if a patch is necessary. This is because the private function will continue to refer to the private implementation and the pattern doesn't apply to public members, only to functions. 39 | 40 | Public object members which refer to private variables are also subject to the no-patch rule notes above. 41 | */ 42 | 43 | //you can't do this: 44 | cartModule.removeItem = function(index) { cart.pop(); return cart.sort(); } // you have no access to cart. 45 | 46 | -------------------------------------------------------------------------------- /namespacing/automated_nesting.js: -------------------------------------------------------------------------------- 1 | // top-level namespace being assigned an object literal 2 | var myApp = myApp || {}; 3 | 4 | var extend = function(parent, namespaces) { 5 | var namespaces = namespaces.split('.'); 6 | for(var i=0; i < namespaces.length; i++) { 7 | if (!parent[namespaces[i]]) parent[namespaces[i]] = {}; 8 | parent = parent[namespaces[i]]; 9 | } 10 | return parent; 11 | } 12 | 13 | //Useage 14 | extend(myApp, 'moduleA.moduleB') 15 | console.log(myApp) // { moduleA: { moduleB: {} } } 16 | -------------------------------------------------------------------------------- /namespacing/iife.js: -------------------------------------------------------------------------------- 1 | /* 2 | http://benalman.com/news/2010/11/immediately-invoked-function-expression/ 3 | Immediately-invoked Function Expressions is effectively an unnamed function, immediately invoked after it's been defined (self-executing or self-invoked ). 4 | 5 | IIFEs are a popular approach to encapsulating application logic to protect it from the global namespace but also have their use in the world of namespacing. 6 | */ 7 | 8 | var myApp = myApp || {}; 9 | (function(namespace) { 10 | namespace.foo = function() { 11 | return namespace.bar; 12 | }; 13 | namespace.bar = "bar"; 14 | }(myApp)); 15 | 16 | // another way of writing it: 17 | (function(namespace) { 18 | namespace.foo = function() { 19 | return namespace.bar; 20 | }; 21 | namespace.bar = "bar"; 22 | })(myApp); 23 | 24 | 25 | // non-namespace useage: 26 | var App = function() { 27 | (function(app) { 28 | // some initialization logic 29 | app.bar = "bar"; 30 | 31 | }(this)) 32 | this.foo = function() { 33 | return this.bar; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /namespacing/injection.js: -------------------------------------------------------------------------------- 1 | /* 2 | Namespace injection is another variation on the IIFE where we "inject" the methods and properties for a specific namespace from within a function wrapper using this as a namespace proxy. The benefit this pattern offers is easy application of functional behaviour to multiple objects or namespaces and can come in useful when applying a set of base methods to be built on later (e.g. getters and setters). 3 | */ 4 | 5 | var myApp = myApp || {}; 6 | myApp.utils = {}; 7 | 8 | (function() { 9 | var val = 5; 10 | this.getValue = function () { 11 | return val; 12 | }; 13 | }.apply(myApp.utils)); 14 | -------------------------------------------------------------------------------- /namespacing/namespacing.md: -------------------------------------------------------------------------------- 1 | Namespaces 2 | ========== 3 | Namespaces can be found in almost any serious JavaScript application. Unless we're working with a simple code-snippet, it's imperative that we do our best to ensure that we're implementing namespacing correctly as it's not just simple to pick-up, it'll also avoid third party code clobbering our own. The patterns we'll be examining in this section are: 4 | 5 | - Automated nested 6 | - Immediately-invoked Function Expressions (IIFE) 7 | - Injection 8 | - Object literal notation 9 | - Nested namespacing 10 | - Prefix 11 | - Single global variables 12 | -------------------------------------------------------------------------------- /namespacing/nested.js: -------------------------------------------------------------------------------- 1 | var myApp = myApp || {}; 2 | myApp.models = { 3 | views: { 4 | pages: {} 5 | } 6 | } 7 | // OR 8 | myApp.models = myApp.models || {}; 9 | myApp.models.views = myApp.models.views || {}; 10 | myApp.models.views.pages = myApp.models.views.pages || {}; 11 | -------------------------------------------------------------------------------- /namespacing/object_literal.js: -------------------------------------------------------------------------------- 1 | /* 2 | Object literal notation can be thought of as an object containing a collection of key:value pairs with a colon separating each pair of keys and values where keys can also represent new namespaces. 3 | Object literals have the advantage of not polluting the global namespace but assist in organizing code and parameters logically. They are truly beneficial if we wish to create easily-readable structures that can be expanded to support deep nesting. Unlike simple global variables, object literals often also take into account tests for the existence of a variable by the same name so the chances of collision occurring are significantly reduced. 4 | 5 | */ 6 | var myApp = { 7 | foo: function() { 8 | return this.bar; 9 | }, 10 | bar: 'bar' 11 | } 12 | 13 | // add/modify properties: 14 | myApp.oterhBar = 'otherBar'; 15 | myApp.bar = 'foo'; 16 | 17 | -------------------------------------------------------------------------------- /namespacing/prefix.js: -------------------------------------------------------------------------------- 1 | /* 2 | One solution to namespacing, as mentioned by Peter Michaux, is to use prefix namespacing. It's a simple concept at heart, but the idea is we select a unique prefix namespace we wish to use (in this example, myApplication_) and then define any methods, variables or other objects after the prefix as follows: 3 | */ 4 | 5 | var myApplication_propertyA = {}; 6 | var myApplication_propertyB = {}; 7 | function myApplication_myMethod(){ 8 | //... 9 | } 10 | 11 | /* 12 | The biggest issue with the pattern is that it can result in a large number of global objects once our application starts to grow. There is also quite a heavy reliance on our prefix not being used by any other developers in the global namespace, so be careful if opting to use this. 13 | */ 14 | -------------------------------------------------------------------------------- /namespacing/single_global_variable.js: -------------------------------------------------------------------------------- 1 | /* 2 | One popular pattern for namespacing in JavaScript is opting for a single global variable as our primary object of reference. A skeleton implementation of this where we return an object with functions and properties can be found below: 3 | */ 4 | 5 | var myApp = (function () { 6 | var bar = "bar"; 7 | var foo = function() { 8 | return bar; 9 | } 10 | return { 11 | foo: foo 12 | } 13 | })(); 14 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | Introduce Javascript Design Pattern: 2 | - Namespace patterns: 3 | - Automated nested 4 | - Immediately-invoked Function Expressions (IIFE) 5 | - Injection 6 | - Object literal notation 7 | - Nested namespacing 8 | - Prefix 9 | - Single global variables 10 | - Module 11 | - Adapter 12 | - Builder 13 | - Composite 14 | - Command 15 | - Constructor 16 | - Iterator 17 | - Pub/Sub 18 | - Singleton 19 | --------------------------------------------------------------------------------