May 2016
TehranJS
Seyed Naser Hassani
Freelance Frontend Developer
Before the topic,
There were something you may know…
Good authors divide their books into chapters and sections;
good programmers divide their programs into modules.
good product made with
good parts.
good parts is:
CAPSULAR (self-contained)
Encapsulation,
is an Object Oriented Programming concept that binds together the data and functions that manipulate the data, and that keeps both safe from outside interference and misuse.
Class
Variable
Method
Dependency WAR
<script src=“app.js”></script>
<script src=“jquery.min.js></script>
Uncaught Referencer Error: jQuery is not defined.
<script src=“jquery.min.js></script>
<script src=“app.js”></script>
Maintainability
Namespacing
Reusability
Modules resolve:
javascript module:
solutions
Ad-Hoc Solution:
Anonymous closure
(function () {
// We keep these variables private inside this closure scope
var myGrades = [93, 95, 88, 0, 55, 91];
var average = function() {
var total = myGrades.reduce(function(accumulator, item) {
return accumulator + item}, 0);
return 'Your average grade is ' + total / myGrades.length + '.';
}
var failing = function(){
var failingGrades = myGrades.filter(function(item) {
return item < 70;});
return 'You failed ' + failingGrades.length + ' times.';
}
console.log(failing());
}());
// ‘You failed 2 times.’
Anonymous closure
Ad-Hoc Solution:
Global Import
(function (globalVariable) {
// Keep this variables private inside this closure scope
var privateFunction = function() {
console.log('Shhhh, this is private!');
}
// Expose the below methods via the globalVariable interface while
// hiding the implementation of the method within the
// function() block
globalVariable.each = function(collection, iterator) {
if (Array.isArray(collection)) {
for (var i = 0; i < collection.length; i++) {
iterator(collection[i], i, collection);
}
} else {
for (var key in collection) {
iterator(collection[key], key, collection);
}
}
};
globalVariable.map = function(collection, iterator) {
var mapped = [];
globalUtils.each(collection, function(value, key, collection) {
mapped.push(iterator(value));
});
return mapped;
};
}(globalVariable));
Global Import
Ad-Hoc Solution:
Object Interface
var myGradesCalculate = (function () {
// Keep this variable private inside this closure scope
var myGrades = [93, 95, 88, 0, 55, 91];
// Expose these functions via an interface while hiding
// the implementation of the module within the function() block
return {
average: function() {
var total = myGrades.reduce(function(accumulator, item) {
return accumulator + item;
}, 0);
return'Your average grade is ' + total / myGrades.length + '.';
},
failing: function() {
var failingGrades = myGrades.filter(function(item) {
return item < 70;
});
return 'You failed ' + failingGrades.length + ' times.';
}
}
})();
myGradesCalculate.failing(); // 'You failed 2 times.'
myGradesCalculate.average(); // 'Your average grade is 70.33333333333333.'
Object Interface
Ad-Hoc Solution:
The Revealing Module Pattern
var myRevealingModule = (function () {
var privateVar = "JavaScript",
publicVar = "Hey there!";
function privateFunction() {
console.log( "Name:" + privateVar );
}
function publicSetName( strName ) {
privateVar = strName;
}
function publicGetName() {
privateFunction();
}
// Reveal public pointers to
// private functions and properties
return {
setName: publicSetName,
greeting: publicVar,
getName: publicGetName
};
})();
myRevealingModule.setName( "Tehran JS" );
The Revealing Module Pattern
but, we need more...
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Backbone.js Todos</title>
<link rel="stylesheet" href="todos.css"/>
</head>
<body>
<script src="../../test/vendor/json2.js"></script>
<script src="../../test/vendor/jquery.js"></script>
<script src="../../test/vendor/underscore.js"></script>
<script src="../../backbone.js"></script>
<script src="../backbone.localStorage.js"></script>
<script src="todos.js"></script>
</body>
<!-- (...) -->
</html>
Backbonjs-todo.html
javascript module:
other solutions
CommonJS or AMD or ES2015
To be or not to be,
?
CommonJS
// In circle.js
const PI = Math.PI;
exports.area = (r) => PI * r * r;
exports.circumference = (r) => 2 * PI * r;
// In some file
const circle = require('./circle.js');
console.log( `The area of a circle of radius 4 is ${circle.area(4)}`);
CommonJS Module
AMD (Asynchronous Module Definition)
//Calling define with a dependency array and a factory function
define(['dep1', 'dep2'], function (dep1, dep2) {
//Define the module value by returning a value.
return function () {};
});
// Or:
define(function (require) {
var dep1 = require('dep1'),
dep2 = require('dep2');
return function () {};
});
AMD Module
ES2015 (native)
//------ lib.js ------
export const sqrt = Math.sqrt;
export function square(x) {
return x * x;
}
export function diag(x, y) {
return sqrt(square(x) + square(y));
}
//------ main.js ------
import { square, diag } from 'lib';
console.log(square(11)); // 121
console.log(diag(4, 3)); // 5
ES2015 Module
System.import('some_module')
.then(some_module => {
// Use some_module
})
.catch(error => {
...
});
Promise.all(
['module1', 'module2', 'module3']
.map(x => System.import(x)))
.then(([module1, module2, module3]) => {
// Use module1, module2, module3
});
ES2015 Module (Importing modules and loading scripts)
appendix:
(function (root, factory) {
if (typeof define === 'function' && define.amd)
{
// AMD
define(['myModule', 'myOtherModule'], factory);
}
else if (typeof exports === 'object')
{
// CommonJS
module.exports = factory(require('myModule'), require('myOtherModule'));
}
else {
// Browser globals (Note: root is window)
root.returnExports = factory(root.myModule, root.myOtherModule);
}
}(this, function (myModule, myOtherModule) {
// Methods
function notHelloOrGoodbye(){}; // A private method
function hello(){}; // A public method because it's returned (see below)
function goodbye(){}; // A public method because it's returned (see below)
// Exposed public methods
return {
hello: hello,
goodbye: goodbye
}
}));
UMD Module
console.thanks('THE END');
QUESTION?