Created
January 12, 2016 18:31
-
-
Save dd3141592/b5328f8881f4147b5139 to your computer and use it in GitHub Desktop.
crib notes and some examples from "JavaScript Patterns" by Stoyan Stefanov //Chapter 4 Functions
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta name="CH 4 functions" content="Javascript Patterns"> | |
<meta charset="utf-8"> | |
<title>JS Bin</title> | |
</headJavascript patterns | |
<body> | |
Javascript Patterns, by Stoyan Stefanov (O'Reilly). Copyright 2010 Yahoo!, Inc., 9780596806750. | |
<script id="jsbin-javascript"> | |
//My crib notes from "JavaScript Patterns" by Stoyan Stefanov | |
//Chapter 4 functions | |
//includes some examples too | |
//you will need to buy the book - these notes are sketchy and for review & reference only | |
"use strict"; | |
//functions are first class objects | |
//you can delete them, augment them, assign them | |
//references copied to other objects | |
//can have their own methods and properties, pass as arguments, | |
//return them from other functions | |
//can be created dynamically at runtime | |
//provide scope - there's only function scope | |
//Named function expressions | |
var add = function add(a,b){ | |
return a + b; | |
}; | |
//this produces an unnamed function expression | |
var add = function(a,b){ | |
return a + b; | |
}; | |
//also function declarations | |
function zebra(){ | |
// | |
} | |
//passing functions, using functions in object literals - these both | |
//use function expressions | |
//examples | |
// callMe(function me(){ | |
//named function expression | |
//}); | |
var x = { | |
yahoo: function(){ | |
//function expression | |
} | |
}; | |
//function declarations can only be defined in global scope or function scope | |
// they can't be assigned to other variables or used as parameters when | |
// calling functions | |
//example | |
function fooBar(){ | |
return 1; | |
} | |
var addEm = function(a,b){ | |
return a() + b; | |
}; | |
console.log(addEm(fooBar, 2)); | |
//but this won't work as expected | |
console.log(add(fooBar,2)); | |
//function name property - useful for debugging, recursive calls | |
// if this not needed then anonymous function expressions less verbose | |
//Function Hoisting | |
//here lies a difference between function declarations and named function | |
//expressions | |
//var z hoisted to top of scope during 'parsing' or | |
//'compiling' - so be careful of calling it before the function expression | |
//is defined | |
function z(){ | |
return "global z"; | |
} | |
function y(){ | |
return "global y"; | |
} | |
console.log(z()); | |
function holyHoisting(){ | |
console.log(y()); | |
//connsole.log(z()); typeerror: z is not a function | |
var z = function z(){ | |
return "local z"; | |
}; | |
function y(){ | |
return "holy Hoisting Batman!"; | |
} | |
} | |
holyHoisting(); | |
//Callback Pattern | |
//callbacks and scope | |
//if callback uses 'this' - what 'this' refers to could be the global | |
//object or the DOM object - incorrectly. | |
//remedy - use call with parameters = callback name and the object you | |
//want 'this' to refer to | |
//examples | |
var myOjb = { | |
paint: function(){ | |
return this.color; | |
}, | |
color: "green" | |
}; | |
//to use this instead of function(callback) | |
//use function(callback, callback_ojb) | |
var findNodes = function(callback, callback_obj){ | |
//... | |
if(typeof callback === 'function'){ | |
callback.call(callback_obj); | |
} | |
//... | |
}; | |
//Or | |
var findNodes = function(callback, callback_obj){ | |
//... | |
if(typeof callback === 'string'){ | |
callback = callback_obj[callback]; | |
} | |
if(typeof callback === 'function'){ | |
callback.call(callback_obj); | |
} | |
//... | |
}; | |
//returning functions | |
// example of a function that counts everytime you call it | |
var counter = function(){ | |
var count = 0; | |
return function(){ | |
console.log(count); | |
count++; | |
}; | |
}; | |
var next = counter(); | |
for(var i = 0; i < 3; i++){ | |
next(); | |
} | |
//self-defining functions | |
//example | |
var myOwnDef = function(){ | |
console.log("I'm doing some initial startup work"); | |
myOwnDef = function(){ | |
console.log("Now I always do this thing"); | |
}; | |
}; | |
//myOwnDef(); | |
//myOwnDef(); | |
//assign properties to the function? | |
myOwnDef.readStr = "new property"; | |
//what if someone does this? | |
var useMyOwnDef = myOwnDef; | |
//never redefines the myOwnDef function | |
useMyOwnDef(); | |
useMyOwnDef(); | |
console.log(useMyOwnDef.readStr); | |
console.log(myOwnDef.readStr); | |
var myOwnSetUp = function(){ | |
console.log('set UP a read string property'); | |
myOwnSetUp = function(string){ | |
console.log(string); | |
}; | |
}; | |
myOwnSetUp.readStr = "new input string"; | |
myOwnSetUp(); | |
myOwnSetUp(myOwnSetUp.readStr); | |
//Immediate functions | |
//execute function immediately after it's defined | |
//parameters of an immediate function | |
//example: global passed in | |
//var o = function(global){ | |
// | |
//}(this); | |
var global = this; | |
//returned values from an immediate function | |
var o = { | |
name: (function(g){ | |
return g.name; | |
}(global)), | |
message : function(){ | |
return "global name: " + this.name; | |
} | |
}; | |
console.log(o.message()); | |
//immediate object initialization | |
//example | |
({ | |
init: function(){ | |
console.log(this.message); | |
}, | |
message: "i'm ok and you're ok!" | |
}).init(); | |
//() serves as a grouping operator above - saying it's an object literal | |
//not a block of code | |
//not polluting global namespace | |
//suitable to one - off tasks | |
//local helper functions | |
//may not minify well | |
//useful pattern to use when doing tasks like browser sniffing - | |
// memoization pattern | |
// use function properties to cache function results | |
//example | |
var memoized = function(){ | |
//create a cache key - jason stringify if it's not primitive type | |
var paramArray = Array.prototype.slice.call(arguments), | |
cacheKey = JSON.stringify(paramArray), | |
length, | |
result; | |
//if result is cached return it | |
if(!memoized.cached[cacheKey]){ | |
//.... expensive steps here | |
length = paramArray.length; | |
result = 0; | |
console.log(length); | |
for(var j = 0; j < length; j += 1){ | |
result += paramArray[j]* 3.141592654; | |
} | |
console.log('finished calc loop'); | |
memoized.cached[cacheKey] = result; | |
} | |
return memoized.cached[cacheKey]; | |
}; | |
memoized.cached = {}; | |
console.log(memoized(1.0,2.0,3.0,4.0,5,6,7,8,9,10)); | |
console.log(memoized(1.0,2.0,3.0,4.0,5,6,7,8,9,10)); | |
//Configuration Objects | |
//use a configuration object instead of long parameter lists - maybe with | |
//some optional and non optional parameters | |
//example | |
var conf = { | |
userName : "ddnoname", | |
firstName: "dee", | |
lastName: "for" | |
}; | |
//call function | |
// f(conf); | |
//rather than for example: | |
// f(firstName,lastName, null, null, userName); | |
//but parameters cannot be minified | |
//Curry | |
// partial function application | |
// function application | |
// Function.prototype.apply() | |
// Function.prototype.call() | |
//partial application | |
// returns a function | |
//Currying | |
// like turning add(5,4) into add(5)(4) | |
//example | |
//accepts a partial list of args | |
function add(x1,y1) { | |
var oldx = x1, | |
oldy = y1; | |
if(typeof oldy === "undefined"){ | |
return function(newy){ | |
return oldx + newy; | |
}; | |
} | |
return x1 + y1; | |
} | |
console.log(add(4)(5)); | |
var addPI = add(3.141592654); | |
console.log(addPI(1000)); | |
</script> | |
<script id="jsbin-source-javascript" type="text/javascript">//My crib notes from "JavaScript Patterns" by Stoyan Stefanov | |
//Chapter 4 functions | |
//includes some examples too | |
//you will need to buy the book - these notes are sketchy and for review & reference only | |
"use strict"; | |
//functions are first class objects | |
//you can delete them, augment them, assign them | |
//references copied to other objects | |
//can have their own methods and properties, pass as arguments, | |
//return them from other functions | |
//can be created dynamically at runtime | |
//provide scope - there's only function scope | |
//Named function expressions | |
var add = function add(a,b){ | |
return a + b; | |
}; | |
//this produces an unnamed function expression | |
var add = function(a,b){ | |
return a + b; | |
}; | |
//also function declarations | |
function zebra(){ | |
// | |
} | |
//passing functions, using functions in object literals - these both | |
//use function expressions | |
//examples | |
// callMe(function me(){ | |
//named function expression | |
//}); | |
var x = { | |
yahoo: function(){ | |
//function expression | |
} | |
}; | |
//function declarations can only be defined in global scope or function scope | |
// they can't be assigned to other variables or used as parameters when | |
// calling functions | |
//example | |
function fooBar(){ | |
return 1; | |
} | |
var addEm = function(a,b){ | |
return a() + b; | |
}; | |
console.log(addEm(fooBar, 2)); | |
//but this won't work as expected | |
console.log(add(fooBar,2)); | |
//function name property - useful for debugging, recursive calls | |
// if this not needed then anonymous function expressions less verbose | |
//Function Hoisting | |
//here lies a difference between function declarations and named function | |
//expressions | |
//var z hoisted to top of scope during 'parsing' or | |
//'compiling' - so be careful of calling it before the function expression | |
//is defined | |
function z(){ | |
return "global z"; | |
} | |
function y(){ | |
return "global y"; | |
} | |
console.log(z()); | |
function holyHoisting(){ | |
console.log(y()); | |
//connsole.log(z()); typeerror: z is not a function | |
var z = function z(){ | |
return "local z"; | |
}; | |
function y(){ | |
return "holy Hoisting Batman!"; | |
} | |
} | |
holyHoisting(); | |
//Callback Pattern | |
//callbacks and scope | |
//if callback uses 'this' - what 'this' refers to could be the global | |
//object or the DOM object - incorrectly. | |
//remedy - use call with parameters = callback name and the object you | |
//want 'this' to refer to | |
//examples | |
var myOjb = { | |
paint: function(){ | |
return this.color; | |
}, | |
color: "green" | |
}; | |
//to use this instead of function(callback) | |
//use function(callback, callback_ojb) | |
var findNodes = function(callback, callback_obj){ | |
//... | |
if(typeof callback === 'function'){ | |
callback.call(callback_obj); | |
} | |
//... | |
}; | |
//Or | |
var findNodes = function(callback, callback_obj){ | |
//... | |
if(typeof callback === 'string'){ | |
callback = callback_obj[callback]; | |
} | |
if(typeof callback === 'function'){ | |
callback.call(callback_obj); | |
} | |
//... | |
}; | |
//returning functions | |
// example of a function that counts everytime you call it | |
var counter = function(){ | |
var count = 0; | |
return function(){ | |
console.log(count); | |
count++; | |
}; | |
}; | |
var next = counter(); | |
for(var i = 0; i < 3; i++){ | |
next(); | |
} | |
//self-defining functions | |
//example | |
var myOwnDef = function(){ | |
console.log("I'm doing some initial startup work"); | |
myOwnDef = function(){ | |
console.log("Now I always do this thing"); | |
}; | |
}; | |
//myOwnDef(); | |
//myOwnDef(); | |
//assign properties to the function? | |
myOwnDef.readStr = "new property"; | |
//what if someone does this? | |
var useMyOwnDef = myOwnDef; | |
//never redefines the myOwnDef function | |
useMyOwnDef(); | |
useMyOwnDef(); | |
console.log(useMyOwnDef.readStr); | |
console.log(myOwnDef.readStr); | |
var myOwnSetUp = function(){ | |
console.log('set UP a read string property'); | |
myOwnSetUp = function(string){ | |
console.log(string); | |
}; | |
}; | |
myOwnSetUp.readStr = "new input string"; | |
myOwnSetUp(); | |
myOwnSetUp(myOwnSetUp.readStr); | |
//Immediate functions | |
//execute function immediately after it's defined | |
//parameters of an immediate function | |
//example: global passed in | |
//var o = function(global){ | |
// | |
//}(this); | |
var global = this; | |
//returned values from an immediate function | |
var o = { | |
name: (function(g){ | |
return g.name; | |
}(global)), | |
message : function(){ | |
return "global name: " + this.name; | |
} | |
}; | |
console.log(o.message()); | |
//immediate object initialization | |
//example | |
({ | |
init: function(){ | |
console.log(this.message); | |
}, | |
message: "i'm ok and you're ok!" | |
}).init(); | |
//() serves as a grouping operator above - saying it's an object literal | |
//not a block of code | |
//not polluting global namespace | |
//suitable to one - off tasks | |
//local helper functions | |
//may not minify well | |
//useful pattern to use when doing tasks like browser sniffing - | |
// memoization pattern | |
// use function properties to cache function results | |
//example | |
var memoized = function(){ | |
//create a cache key - jason stringify if it's not primitive type | |
var paramArray = Array.prototype.slice.call(arguments), | |
cacheKey = JSON.stringify(paramArray), | |
length, | |
result; | |
//if result is cached return it | |
if(!memoized.cached[cacheKey]){ | |
//.... expensive steps here | |
length = paramArray.length; | |
result = 0; | |
console.log(length); | |
for(var j = 0; j < length; j += 1){ | |
result += paramArray[j]* 3.141592654; | |
} | |
console.log('finished calc loop'); | |
memoized.cached[cacheKey] = result; | |
} | |
return memoized.cached[cacheKey]; | |
}; | |
memoized.cached = {}; | |
console.log(memoized(1.0,2.0,3.0,4.0,5,6,7,8,9,10)); | |
console.log(memoized(1.0,2.0,3.0,4.0,5,6,7,8,9,10)); | |
//Configuration Objects | |
//use a configuration object instead of long parameter lists - maybe with | |
//some optional and non optional parameters | |
//example | |
var conf = { | |
userName : "ddnoname", | |
firstName: "dee", | |
lastName: "for" | |
}; | |
//call function | |
// f(conf); | |
//rather than for example: | |
// f(firstName,lastName, null, null, userName); | |
//but parameters cannot be minified | |
//Curry | |
// partial function application | |
// function application | |
// Function.prototype.apply() | |
// Function.prototype.call() | |
//partial application | |
// returns a function | |
//Currying | |
// like turning add(5,4) into add(5)(4) | |
//example | |
//accepts a partial list of args | |
function add(x1,y1) { | |
var oldx = x1, | |
oldy = y1; | |
if(typeof oldy === "undefined"){ | |
return function(newy){ | |
return oldx + newy; | |
}; | |
} | |
return x1 + y1; | |
} | |
console.log(add(4)(5)); | |
var addPI = add(3.141592654); | |
console.log(addPI(1000)); | |
</script></body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment