Created by Paul Balchin
← → ↑ ↓ navigate
Esc bird's eye view
Functions attached to object trees.
//SIMPLIFIED EXAMPLE
mattel = {};
mattel.loginreg = {};
mattel.loginreg.variables = {};
mattel.loginreg.login = function(){};
mattel.loginreg.logout = function(){};
mattel.loginreg.isUnder13 = function(){};
mattel.loginreg.isOver13 = function(){};
↓
What we really want are functions that look like objects
var functionName = function(){
console.log('called functionName()');
};
↓
Call the function; get a result
//CONSOLE
functionName() → 'called functionName()'
Just add parens at the end
var functionName = function(){
console.log('called functionName()');
}();
//CONSOLE
'called functionName()'
Look ma, no hands!
↓
You can wrap the entire function in another set of parens
var functionName = (function(){
console.log('called functionName.init()');
}());
This is a matter of convention only
Think of it as a declaration
The set up
var functionName = (function(){
console.log('called functionName()');
var init = function(){
console.log('called functionName.init()');
};
return {
init: init
};
}());
Call immediately
functionName.init();
Race conditions? External dependencies?
↓
var functionName = (function(){
console.log('called functionName()');
var init = function(){
console.log('called functionName.init()');
};
return {
init: init
};
}());
Call on document ready
$(document).ready(function(){
functionName.init();
});
Where do you put it?
↓
var functionName = (function(){
console.log('called functionName()');
var init = function(){
console.log('called functionName.init()');
};
return {
init: init
};
}());
Call from somewhere in the HTML
<script>
functionName.init();
</script>
↓
Called from partials? Views? Layouts?
var functionName = (function(){
console.log('called functionName()');
// this is an init()
$(document).ready(function(){
console.log('called functionName.document.ready()');
});
}());
//CONSOLE
'called functionName()'
'called functionName.document.ready() '
↓
var functionName = (function(){
var a, b, c;
var functionOne = function(){};
var functionTwo = function(){};
var functionThree = function(){};
// types of inits(): event-driven
$(document).ready(functionName);
$(document).on('click',functionName);
$(window).load(functionName);
$(window).resize(functionName);
// types of inits(): just call it
// (where race conditions don't apply)
functionOne();
}());
var functionName = (function(){
var doSomethingWithHtml = function(){
console.log('called functionName.doSomethingWithHtml()');
};
var doSomethingWithClick = function(){
console.log('called functionName.doSomethingWithClick()');
};
$(document).ready(function(){
// limit usage to specific HTML
if( $('#htmlSelector').length > 0 ){
doSomethingWithHtml();
}
});
}());
↓
var functionName = (function(){
var a, b, c;
var onClickButtonOne = function(){};
var onClickButtonTwo = function(){};
var functionThree = function(){};
var functionFour = function(){};
$(document).ready(function(){
// list of actions only, do the work above
$(document).on('click', '#actionButtonOne', onClickButtonOne);
$(document).on('click', '#actionButtonTwo', onClickButtonTwo);
});
$(window).load(function(){
// list of actions only, do the work above
functionThree();
});
}());
↓
//CONSOLE
functionName → 'undefined' // Wait. What?
var functionName = (function(){
console.log('called functionName()');
}());
//CONSOLE
'called functionName()'
functionName → 'undefined' // WHAT!?
Immediately-invoked functions that return nothing
are fire and forget
If you return nothing, then there's nothing to pass back to the variable name
var functionName = (function(){
console.log('called functionName()');
// return what?
}());
That's a pretty limited option.
↓
var functionName = (function(){
// everything is private by default
var a, b, c;
var functionOne = function(){};
var functionTwo = function(){};
var functionThree = function(){};
// except what is returned as public here
return {
FunctionOne: functionOne,
FunctionTwo: functionTwo
};
}());
//STRUCTURE
functionName → {
FunctionOne: function (){},
FunctionTwo: function (){}
}
You've created a JavaScript namespace!
var namespace = (function(){
var a, b, c;
var functionOne = function(){};
var functionTwo = function(){};
var functionThree = function(){};
return {
FunctionOne: functionOne,
FunctionTwo: functionTwo
};
}());
//STRUCTURE
namespace: {
FunctionOne: function (){},
FunctionTwo: function (){}
}
var namespace = (function(){...}());
var namespace.nestedNamespace1 = (function(){...}());
var namespace.nestedNamespace2 = (function(){...}());
var namespace.nestedNamespace2.nestedNamespace2A = (function(){...}());
var namespace.nestedNamespace2.nestedNamespace2B = (function(){...}());
var namespace.nestedNamespace3 = (function(){...}());
//STRUCTURE
namespace: {
FunctionOne: function (){},
FunctionTwo: function (){},
nestedNamespace1: {
FunctionOne: function (){},
},
nestedNamespace2: {
FunctionOne: function (){},
FunctionTwo: function (){},
FunctionThree: function (){},
NestedNamespace2A: function (){
FunctionOne: function (){},
FunctionTwo: function (){},
},
NestedNamespace2B: function (){},
}
}
var namespace = (function(){
//scoped properties and variables,
//scoped get/set functions for all public properties,
//scoped core functions,
// for each core function
// scoped variables,
// exception handling
// code
//initialization(s),
//public declarations.
}());
var namespace = (function(){
//scoped properties and variables,
// --scoped get/set functions for all public properties,--
//scoped core functions,
// for each core function
// scoped variables,
// exception handling
// code
//initialization(s),
// --public declarations.--
}());
Micro management
* There are exceptions to every rule.
↓
Fire and forget
Keep it simple
(And there's more slides further on)
↓
Liberally.
It won't add to the file size in production because minification will strip it out.
↓
JavaScript files are cached by the browser
↓
Noob
<span onclick="updateUserProfile();">Save your changes</span>
Pro
//HTML
<span class="updateUserProfile">Save your changes</span>
//JAVASCRIPT
$(document).on('click', '.updateUserProfile', onUpdateUserProfile});
Event handlers are your friends
(on click, on document ready, on window load, etc.)
↓
↓
In JavaScript, you usually create a variable for two reasons:
You don't have to create a variable
for the sake of accessing a value.
↓
So similar,
$(object); // <-- example 1
$('selector', object); // <-- example 2
yet so far apart.
$(document).ready(callThisFunction); // <-- example 1 explained
$(jQueryObject).find('string'); // <-- example 2 explained
Don't be afraid to be verbose:
↓
Liberally.
It won't add to the file size in production because minification will strip it out.
↓
Noob
<div style="padding:10px;">
↓
CSS files are cached by the browser
↓
dashed-css-classes for styling
<div class="button-green">
<div class="list-of-products">
camelCaseClasses for JavaScript hooks
<div class="updateUserProfile">
<div class="expandCollapseProductDetails">
Mix and match
<div class="button-green updateUserProfile">
<div class="list-of-products expandCollapseProductDetails">
↓
Use <div> and <span> liberally for your layouts; search engines treat them as "scaffolding" tags and are not considered semantic markup.
↓
Buttons (<button> or <input type="button">) are form elements and are for submitting forms
(You can blame ASP.NET for their abuse. Read on.)
↓
//STANDARD USE
<a href="/product-details.html?id=345">Details for 345</a>
Anchors are for linking one page to another, and the href is required. It is the only HTML tag search engines use to crawl your site if you don't provide them with a site map.
↓
//JAVASCRIPT INTERCEPTION
<a href="/product-details.html?id=345"
onclick="showModal(); return false;">Details for 345</a>
// 1. Provides a URL for search engines to follow.
// 2. When clicked, the user sees a modal instead.
Event handlers, like onclick, are called first and the href last.
Be careful: If you don't return false (here or in the function), the browser will immediately follow the link.
↓
The right way
<a href="/product-details.html?id=345"
onclick="showModal(); return false;">Details for 345</a>
The wrong way
<a href="#" onclick="showModalDetails('345');">Details for 345</a>
// 1. Improper use of a named anchor,
e.g. href="#" means "scroll to top of page, then scroll to # on page".
// 2. No URL for search engines to follow.
// 3. If you don't "return false" you will:
// a. add a "#" to the end of your URL (e.g. "yoursite.com/#")
// b. add an entry to your browser's history
// (ever click once but have to "go back" twice?)
An alternative way
<span onclick="showDetails('345');">Details for 345</span>
// Any element can have event handlers.
End