SlideShare a Scribd company logo
The Mighty JS Function
Timothee Groleau - 2010-11-04
Who I am
●Timothee (Tim) Groleau
●EcmaScript coder for 10+ years (AS1, AS2, JS)
●Currently working at mig33 ( http://mig33.com )
Disclaimer / warnings
●I hope you like black and white
●Spaghetti presentation
●Examples purposely simplistic/stupid to illustrate features
●I have not looked at a real JS VM implementation
●we'll start reaaaaallly simple, then move on to interesting stuff
●coding style not consistent (I had to save spaces in these slides)
●I didn't follow Sebastiaan's advice of splitting content,
(and then I totally regretted it, but it was too late :( )
function factorial (n)
{
var fact = 1;
while (n > 1) fact *= n--;
return fact;
}
x = 5;
res = factorial(x);
alert(x); // 5
alert(res); // 120
// alert(n); // error n is not defined
// alert(fact); // error fact is not defined
What do we have here?
●Function declaration
●Function invocation
●Function arguments and parameters passing (pass by value)
●Local parameters
●Memory reclamation / garbage collection
function average ()
{
if (arguments.length <= 0) return 0;
var total = 0;
for (var i=0; i<arguments.length; i++)
{
total += arguments[i];
}
return total / arguments.length;
}
a = average(3, 5, 7, 9, 11, 8, 2);
alert(a); // 6.428571428571429
What do we have here?
●undeclared arguments
●variable length argument list
●arguments array (!!beware!! FAKE array)
var foo = {x:5}, bar = {x:6};
function whatsMyX()
{
return this.x;
}
foo.getX = whatsMyX;
bar.getX = whatsMyX;
alert( foo.getX() ); // 5
alert( bar.getX() ); // 6
alert( foo.getX === bar.getX ); // true
What do we have here?
●function references can be assigned, just like any variable
●function call operator (), can be used on any valid function reference
●'this' in a function body is dynamically resolved, and resolves to the
object the function is called from
DOMAIN = 'http://www.mig33.com';
function getURL(path)
{
return DOMAIN + path;
}
url = getURL('/about-us/jobs');
alert(url);
What do we have here?
●global variable access inside a function
●scope chain traversal
function getModuloFunc(mod)
{
return function(n)
{
return n % mod;
}
}
mod2 = getModuloFunc(2);
mod3 = getModuloFunc(3);
alert( [mod2(1), mod2(2), mod2(3), mod2(4), mod2(5)] );
alert( [mod3(1), mod3(2), mod3(3), mod3(4), mod3(5)] );
What do we have here?
●a function is being returned from another function
●the inner function is persisted
●when the inner function runs, it has access to the local variables of
the outer function
===> closures!
var x = 5;
function setup(obj) {
var x;
obj.setIt = function(a, b) {
x = a;
y = b;
}
obj.getIt = function() {
return [x, y];
}
}
o = {}; setup(o);
o.setIt(6, 7);
alert(o.getIt()); // [6, 7]
alert( [x, y] ); // [5, 7]
What do we have here?
●2 inner functions are persisted in a global object
●they both have access to the same outer function's scope
●assignment without explicit scope is done to first scope that declares
variable, or to global scope (e.g. 'y' ends up in the global scope)
Concept slide 1 – function declaration
function foo() {}
●named function
●can be forward referenced
foo = function() {}
●anonymous function
●assigned to variable foo
●makes it obvious that the function can be treated like any variable
In both cases, foo is now a reference to a function object, aka a function
reference
Concept slide 2 – functions are first class objects
They can be assigned/accessed like any other variable
function foo(){};
var bar = foo; bar();
var o = {}; o.bla = foo; o.bla();
As a consequence, they can be passed as function parameters, and be
return values from functions
function foo() { alert('hello'); };
function bar1(func) { func(); }
bar1(foo);
function bar2() { return foo; };
bar2()();
Functions can hold data
function foo(){}
bar = foo;
bar.aProperty = 'hello';
alert(foo.aProperty);
Functions are instances of the Function class (more on that later... maybe)
Concept slide 3 – function call operator: ()
The function call operator can be used on anything that evaluate to a
function reference.
var foo = function() {alert('hello');};
foo();
var bar = foo; bar();
var o = {method:foo}; o.method();
var name = 'method'; o[name]();
(function() {alert('hello');})()
var bar2 = function(){ return foo; };
bar2()();
Concept slide 4 – Scopes in javascript
No block scope in JS:
var x = 5;
{
var x = 6;
}
alert(x); // ?
Functions provide scopes
var x = 5;
function foo()
{
var x;
x = 6;
alert(x);
}
foo(); // 6
alert(x); // 5
Concept slide 5 – Scope chain / Lexical scoping
Javascript is lexically scoped (aka: just read it, it makes sense)
var x = 5;
function foo() { alert(x); }
function bar() { var x=6; foo(); }
bar(); // ?
In other words, the scope chain of a function is determined at function
creation, NOT at function invocation
The scope chain is the sequence of objects inspected for variable
resolution. Think of it as a linked list.
Concept slide 6 – Closures / Scope chain / Memory considerations I
function foo()
{
var someLargeString = 'bla';
var someOtherLargeString = 'bli';
var theNumberIneed = 5;
return function(n) {
return n + theNumberIneed;
}
}
bar = foo();
alert( bar(5) ); // 10
What happened to someLargeString and someOtherLargeString?
They are in memory for as long as a reference to the inner function exists,
but they can never be reached.
Concept slide 7 – Closures / Scope chain / Memory considerations II
Want proof?
function foo()
{
var someLargeString = 'bla';
var someOtherLargeString = 'bli';
var theNumberIneed = 5;
return function(name) {
return eval(name);
}
}
getFromScope = foo();
alert( getFromScope('someLargeString') ); // bla
alert( getFromScope('someOtherLargeString') ); // bli
alert( getFromScope('theNumberIneed') ); // 5
Concept slide 8 – Closures / Scope chain / Memory considerations III
var global_var = 2;
function f(arg)
{
var local_var_f = arg;
alert([local_var_f, global_var]);
return function(arg)
{
alert([
arg,
local_var_f,
global_var
]);
}
}
g1 = f(3); //3,2
g1(4); //4,3,2
g1(5); //5,3,2
g2 = f(6); //6,2
g2(7); //7,6,2
g2(8); //8,6,2
Concept slide 9 – Closures / Scope chain / Memory considerations IV
Let's take a look at what's really happening (boo-ring... sorry)
1) At function creation time, a 'hidden' reference is stored in the function to
point to the CURRENT scope object, this basically becomes the start of the
scope chain.
2) At function invocation
a) a new object is created to become the current scope
b) all local variables, function parameters, and arguments array are stored
in that object (i.e. 'var' is a keyword to add new members to the scope
object)
c) the new object gets the hidden link to point to the function's scope chain
d) when end of the function is reached, the scope object gets destroyed,
all local variables it carries are removed (yeah, garbage collection!)
3) IF an inner function is persisted (returned or assigned to a global object),
then the 'hidden link' to the current scope is also persisted, and since ref
count is not zero, the scope object (and ALL its local variables) are NOT
garbage collected
Concept slide 10 – to closure or not to closure? I
function setup(obj)
{
var someVar = 'bla';
obj.count = 0;
obj.aMethod = function()
{
this.count++;
}
}
o1 = {}; setup(o1);
o2 = {}; setup(o2);
Good or bad?
alert( o1.aMethod === o2.aMethod ); // false
Concept slide 11 – to closure or not to closure? II
function _method()
{
this.count++;
}
function setup(obj)
{
var someVar = 'bla';
obj.count = 0;
obj.aMethod = _method;
}
o1 = {}; setup(o1);
o2 = {}; setup(o2);
alert( o1.aMethod === o2.aMethod ); // true
Putting it all together – private scopes
(function(){
var DOMAIN = 'http://www.mig33.com';
getURL = function(path)
{
return DOMAIN + path;
}
})();
url = getURL('/about-us/jobs');
alert(url);
Putting it all together – Classes with private statics
(function(){
// private static
var prefix = 'M33_WIDGET_';
var count = 0;
var domain = 'http://www.mig33.com';
MyClass = function() {
this.id = prefix + (++count);
};
o = MyClass.prototype;
o.method1 = function(path) { /* … */ };
})();
m = new MyClass();
alert( m.id );
Putting it all together – Instance privates (CrockFord style)
function Foo(blarg)
{
var self = this; // Capture self-ref in closure
this.datum = blarg;
var private_data = "whatever"; // Captured in closure
this.standard_method = function() {
return this.datum;
};
function private_method() {
self.datum += 1; // Accesses member via closure
return private_data; // Accesses closure
}
this.privileged_method = function() {
private_data += "!"; // Accesses closure
return private_method();
};
}
o = new Foo(5);
o.privileged_method();
alert( o.bar() );
alert( o.private_data ); // undefined
Putting it all together – Classes with scopes, My own practice
Enclosing closure for each class definition
=> allow for private static vars and methods
Naming convention on instance private vars and methods (pragmatic, saves
memory, easier to test)
Enclosing closure for each namespace.
Whatever – Recursion and scope chain I
function factorial(n)
{
if (n < 2) return 1;
return n * factorial(n-1);
}
Math.factorial = factorial;
alert( Math.factorial(5) ); // 120
// later in code
factorial = function(n) {
return 1;
}
alert( Math.factorial(5) ); // 5
Whatever – Recursion and scope chain II
function factorial(n)
{
if (n < 2) return 1;
return n * arguments.callee(n-1);
}
Math.factorial = factorial;
alert( Math.factorial(5) ); // 120
// later in code
factorial = function(n) {
return 1;
}
alert( Math.factorial(5) ); // 120
Whatever – Arguments.callee for function static variables
function click()
{
if (--arguments.callee.tries < 0)
{
alert('forbidden'); return false;
}
alert('click'); return true;
}
click.tries = 3;
click(); // click
click(); // click
click(); // click
click(); // forbidden
Function class – Function.apply / Function.call I
Function.apply and function.call are used to manually set the meaning of
'this'
function getX(y, z)
{
alert( [this.x, y, z] );
}
o1 = {x:5};
o2 = {x:6};
getX.apply(o1, [6, 7]);
getX.apply(o2, [7, 8]);
getX.call(o1, 6, 7);
getX.call(o2, 7, 8);
Function class – Function.apply / Function.call II
variable length arguments are typically not known in advance, use
function.apply to pass an array that will translate to arguments
function average ()
{
if (arguments.length <= 0) return 0;
var total = 0;
for (var i=0; i<arguments.length; i++)
{
total += arguments[i];
}
return total / arguments.length;
}
data = [3, 5, 7, 9, 11, 8, 2];
a = average.apply(null, data);
alert(a); // 6.428571428571429
Delegation I
function MyClass(name){
this.name = name;
this.setup();
}
MyClass.prototype.setup = function() {
var b = document.getElementsByTagName('body')[0];
b.onclick = this.sayMyName;
}
MyClass.prototype.sayMyName = function() {
alert( this.name );
}
m = new MyClass('tim');
// click in browser => undefined!
Delegation II – Store a reference to 'this' in the closure
function MyClass(name) {
this.name = name;
this.setup();
}
MyClass.prototype.setup = function() {
var b = document.getElementsByTagName('body')[0];
var self = this;
b.onclick = function(){
self.sayMyName();
}
}
MyClass.prototype.sayMyName = function(){
alert( this.name );
}
m = new MyClass('tim');
// click in browser => tim!
Delegation III – use a helper function with function reference
delegate = function(obj, func)
{
return function()
{
return func.apply(obj, arguments);
}
}
o1 = {
name: 'o1',
sayMyName: function(a){
alert(a + ' ' + this.name)
}
};
o2 = {name: 'o2'};
o2.sayIt = delegate(o1, o1.sayMyName);
o2.sayIt('hello');
Delegation IV – use a helper function with a function name
delegate = function(obj, funcName)
{
return function()
{
return obj[funcName].apply(obj, arguments);
}
}
o1 = {
name: 'o1',
sayMyName: function(a){
alert(a + ' ' + this.name)
}
};
o2 = {name: 'o2'};
o2.sayIt = delegate(o1, 'sayMyName');
o2.sayIt('hello'); // 'hello o1'
Delegation V – allow setting fixed parameters, when delegating
delegate = function(obj, funcName, greeting)
{
return function()
{
return obj[funcName].apply(obj, [greeting]);
}
}
o1 = {
name: 'o1',
sayMyName: function(a){
alert(a + ' ' + this.name)
}
};
o2 = {name: 'o2'};
o2.sayIt = delegate(o1, 'sayMyName', 'bonjour');
o2.sayIt('hello'); // 'bonjour o1'
Trivia I
In a browser, the global scope is the window object itself :)
a = 5;
alert( window.a ); // 5
Trivia II - Assignment without explicit scope
Assignment without explicit scope is done to the first scope object that had
the variable declared locally, or global scope if none:
var x = 5;
function foo()
{
x = 6;
}
foo(); alert(x); // 6
/*======================================*/
var x = 5;
function foo()
{
var x;
return function()
{
x = 6;
}
}
foo()(); alert(x); // 5
Conclusion
Functions in JS are VERY powerful
Closures are probably the most useful feature of JS
Beware, you can get bitten hard, especially with long closures (e.g. jQuery
has one fat outer function scope of 6,500+ lines). Watch out for:
●local variables in outer scopes that are left alive forever
●function duplication where they are not required
Especially true in the days of cool ajaxy libraries like jQuery or ExtJS, which
make it very easy to use closures without completely understanding them.
I'm not bashing jQuery, I looove jQuery, just know your tools well! :D

More Related Content

PPT
Евгений Крутько, Многопоточные вычисления, современный подход.
PPTX
Lexical environment in ecma 262 5
PDF
Антон Нонко, Классические строки в C++
PDF
Clang tidy
PPTX
Pro typescript.ch03.Object Orientation in TypeScript
PDF
Qt Rest Server
PDF
Welcome to Modern C++
PPTX
Алексей Кутумов, Вектор с нуля
Евгений Крутько, Многопоточные вычисления, современный подход.
Lexical environment in ecma 262 5
Антон Нонко, Классические строки в C++
Clang tidy
Pro typescript.ch03.Object Orientation in TypeScript
Qt Rest Server
Welcome to Modern C++
Алексей Кутумов, Вектор с нуля

What's hot (20)

PDF
Oxygine 2 d objects,events,debug and resources
PPTX
Дмитрий Нестерук, Паттерны проектирования в XXI веке
PDF
Kirk Shoop, Reactive programming in C++
PPTX
How Data Flow analysis works in a static code analyzer
PDF
C++ game development with oxygine
PDF
PVS-Studio in 2021 - Error Examples
PPTX
модели акторов в с++ миф или реальность
PDF
C++ L08-Classes Part1
PDF
Modern C++ Concurrency API
PDF
Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и к...
PDF
Алексей Кутумов, Coroutines everywhere
PPTX
Evgeniy Muralev, Mark Vince, Working with the compiler, not against it
PDF
C++ aptitude
PDF
서버 개발자가 바라 본 Functional Reactive Programming with RxJava - SpringCamp2015
PDF
Message in a bottle
PDF
Антон Бикинеев, Writing good std::future&lt; C++ >
PDF
Коварный code type ITGM #9
PDF
4. Обработка ошибок, исключения, отладка
PPTX
Дмитрий Демчук. Кроссплатформенный краш-репорт
PDF
C++ L05-Functions
Oxygine 2 d objects,events,debug and resources
Дмитрий Нестерук, Паттерны проектирования в XXI веке
Kirk Shoop, Reactive programming in C++
How Data Flow analysis works in a static code analyzer
C++ game development with oxygine
PVS-Studio in 2021 - Error Examples
модели акторов в с++ миф или реальность
C++ L08-Classes Part1
Modern C++ Concurrency API
Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и к...
Алексей Кутумов, Coroutines everywhere
Evgeniy Muralev, Mark Vince, Working with the compiler, not against it
C++ aptitude
서버 개발자가 바라 본 Functional Reactive Programming with RxJava - SpringCamp2015
Message in a bottle
Антон Бикинеев, Writing good std::future&lt; C++ >
Коварный code type ITGM #9
4. Обработка ошибок, исключения, отладка
Дмитрий Демчук. Кроссплатформенный краш-репорт
C++ L05-Functions
Ad

Viewers also liked (7)

PPTX
P grey kotlerdeliveringvalue
PPTX
Introduction to Client-Side Javascript
PPTX
Code for kombol - Objects and Functions in JS and NodeJS
PPTX
Javascript: master this
PPT
Js ppt
PDF
2015 Upload Campaigns Calendar - SlideShare
PPTX
What to Upload to SlideShare
P grey kotlerdeliveringvalue
Introduction to Client-Side Javascript
Code for kombol - Objects and Functions in JS and NodeJS
Javascript: master this
Js ppt
2015 Upload Campaigns Calendar - SlideShare
What to Upload to SlideShare
Ad

Similar to The mighty js_function (20)

PPT
Object Oriented JavaScript
PDF
Rediscovering JavaScript: The Language Behind The Libraries
PDF
java script functions, classes
PDF
JS OO and Closures
PPTX
Object oriented java script
PPT
JavaScript - Programming Languages course
PPT
Basic Javascript
PDF
JavaScript Primer
PDF
Js in-ten-minutes
KEY
Javascript tid-bits
PPTX
Awesomeness of JavaScript…almost
PPT
JavaScript Functions
PPTX
Ajaxworld
PPTX
Lecture 4- Javascript Function presentation
PDF
JavaScript Functions
KEY
Exciting JavaScript - Part I
PDF
Pragmatic JavaScript
PPTX
Java script function
PPT
25-functions.ppt
Object Oriented JavaScript
Rediscovering JavaScript: The Language Behind The Libraries
java script functions, classes
JS OO and Closures
Object oriented java script
JavaScript - Programming Languages course
Basic Javascript
JavaScript Primer
Js in-ten-minutes
Javascript tid-bits
Awesomeness of JavaScript…almost
JavaScript Functions
Ajaxworld
Lecture 4- Javascript Function presentation
JavaScript Functions
Exciting JavaScript - Part I
Pragmatic JavaScript
Java script function
25-functions.ppt

Recently uploaded (20)

PPTX
Big Data Technologies - Introduction.pptx
PDF
cuic standard and advanced reporting.pdf
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PDF
NewMind AI Weekly Chronicles - August'25 Week I
PDF
Electronic commerce courselecture one. Pdf
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PDF
MIND Revenue Release Quarter 2 2025 Press Release
PDF
KodekX | Application Modernization Development
PPTX
Programs and apps: productivity, graphics, security and other tools
PDF
Machine learning based COVID-19 study performance prediction
PDF
Spectral efficient network and resource selection model in 5G networks
PDF
Encapsulation_ Review paper, used for researhc scholars
PPTX
Cloud computing and distributed systems.
PPTX
sap open course for s4hana steps from ECC to s4
PDF
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
PDF
Unlocking AI with Model Context Protocol (MCP)
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
PDF
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
DOCX
The AUB Centre for AI in Media Proposal.docx
Big Data Technologies - Introduction.pptx
cuic standard and advanced reporting.pdf
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
NewMind AI Weekly Chronicles - August'25 Week I
Electronic commerce courselecture one. Pdf
Advanced methodologies resolving dimensionality complications for autism neur...
MIND Revenue Release Quarter 2 2025 Press Release
KodekX | Application Modernization Development
Programs and apps: productivity, graphics, security and other tools
Machine learning based COVID-19 study performance prediction
Spectral efficient network and resource selection model in 5G networks
Encapsulation_ Review paper, used for researhc scholars
Cloud computing and distributed systems.
sap open course for s4hana steps from ECC to s4
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
Unlocking AI with Model Context Protocol (MCP)
Reach Out and Touch Someone: Haptics and Empathic Computing
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
The AUB Centre for AI in Media Proposal.docx

The mighty js_function

  • 1. The Mighty JS Function Timothee Groleau - 2010-11-04
  • 2. Who I am ●Timothee (Tim) Groleau ●EcmaScript coder for 10+ years (AS1, AS2, JS) ●Currently working at mig33 ( http://mig33.com ) Disclaimer / warnings ●I hope you like black and white ●Spaghetti presentation ●Examples purposely simplistic/stupid to illustrate features ●I have not looked at a real JS VM implementation ●we'll start reaaaaallly simple, then move on to interesting stuff ●coding style not consistent (I had to save spaces in these slides) ●I didn't follow Sebastiaan's advice of splitting content, (and then I totally regretted it, but it was too late :( )
  • 3. function factorial (n) { var fact = 1; while (n > 1) fact *= n--; return fact; } x = 5; res = factorial(x); alert(x); // 5 alert(res); // 120 // alert(n); // error n is not defined // alert(fact); // error fact is not defined What do we have here? ●Function declaration ●Function invocation ●Function arguments and parameters passing (pass by value) ●Local parameters ●Memory reclamation / garbage collection
  • 4. function average () { if (arguments.length <= 0) return 0; var total = 0; for (var i=0; i<arguments.length; i++) { total += arguments[i]; } return total / arguments.length; } a = average(3, 5, 7, 9, 11, 8, 2); alert(a); // 6.428571428571429 What do we have here? ●undeclared arguments ●variable length argument list ●arguments array (!!beware!! FAKE array)
  • 5. var foo = {x:5}, bar = {x:6}; function whatsMyX() { return this.x; } foo.getX = whatsMyX; bar.getX = whatsMyX; alert( foo.getX() ); // 5 alert( bar.getX() ); // 6 alert( foo.getX === bar.getX ); // true What do we have here? ●function references can be assigned, just like any variable ●function call operator (), can be used on any valid function reference ●'this' in a function body is dynamically resolved, and resolves to the object the function is called from
  • 6. DOMAIN = 'http://www.mig33.com'; function getURL(path) { return DOMAIN + path; } url = getURL('/about-us/jobs'); alert(url); What do we have here? ●global variable access inside a function ●scope chain traversal
  • 7. function getModuloFunc(mod) { return function(n) { return n % mod; } } mod2 = getModuloFunc(2); mod3 = getModuloFunc(3); alert( [mod2(1), mod2(2), mod2(3), mod2(4), mod2(5)] ); alert( [mod3(1), mod3(2), mod3(3), mod3(4), mod3(5)] ); What do we have here? ●a function is being returned from another function ●the inner function is persisted ●when the inner function runs, it has access to the local variables of the outer function ===> closures!
  • 8. var x = 5; function setup(obj) { var x; obj.setIt = function(a, b) { x = a; y = b; } obj.getIt = function() { return [x, y]; } } o = {}; setup(o); o.setIt(6, 7); alert(o.getIt()); // [6, 7] alert( [x, y] ); // [5, 7] What do we have here? ●2 inner functions are persisted in a global object ●they both have access to the same outer function's scope ●assignment without explicit scope is done to first scope that declares variable, or to global scope (e.g. 'y' ends up in the global scope)
  • 9. Concept slide 1 – function declaration function foo() {} ●named function ●can be forward referenced foo = function() {} ●anonymous function ●assigned to variable foo ●makes it obvious that the function can be treated like any variable In both cases, foo is now a reference to a function object, aka a function reference
  • 10. Concept slide 2 – functions are first class objects They can be assigned/accessed like any other variable function foo(){}; var bar = foo; bar(); var o = {}; o.bla = foo; o.bla(); As a consequence, they can be passed as function parameters, and be return values from functions function foo() { alert('hello'); }; function bar1(func) { func(); } bar1(foo); function bar2() { return foo; }; bar2()(); Functions can hold data function foo(){} bar = foo; bar.aProperty = 'hello'; alert(foo.aProperty); Functions are instances of the Function class (more on that later... maybe)
  • 11. Concept slide 3 – function call operator: () The function call operator can be used on anything that evaluate to a function reference. var foo = function() {alert('hello');}; foo(); var bar = foo; bar(); var o = {method:foo}; o.method(); var name = 'method'; o[name](); (function() {alert('hello');})() var bar2 = function(){ return foo; }; bar2()();
  • 12. Concept slide 4 – Scopes in javascript No block scope in JS: var x = 5; { var x = 6; } alert(x); // ? Functions provide scopes var x = 5; function foo() { var x; x = 6; alert(x); } foo(); // 6 alert(x); // 5
  • 13. Concept slide 5 – Scope chain / Lexical scoping Javascript is lexically scoped (aka: just read it, it makes sense) var x = 5; function foo() { alert(x); } function bar() { var x=6; foo(); } bar(); // ? In other words, the scope chain of a function is determined at function creation, NOT at function invocation The scope chain is the sequence of objects inspected for variable resolution. Think of it as a linked list.
  • 14. Concept slide 6 – Closures / Scope chain / Memory considerations I function foo() { var someLargeString = 'bla'; var someOtherLargeString = 'bli'; var theNumberIneed = 5; return function(n) { return n + theNumberIneed; } } bar = foo(); alert( bar(5) ); // 10 What happened to someLargeString and someOtherLargeString? They are in memory for as long as a reference to the inner function exists, but they can never be reached.
  • 15. Concept slide 7 – Closures / Scope chain / Memory considerations II Want proof? function foo() { var someLargeString = 'bla'; var someOtherLargeString = 'bli'; var theNumberIneed = 5; return function(name) { return eval(name); } } getFromScope = foo(); alert( getFromScope('someLargeString') ); // bla alert( getFromScope('someOtherLargeString') ); // bli alert( getFromScope('theNumberIneed') ); // 5
  • 16. Concept slide 8 – Closures / Scope chain / Memory considerations III var global_var = 2; function f(arg) { var local_var_f = arg; alert([local_var_f, global_var]); return function(arg) { alert([ arg, local_var_f, global_var ]); } } g1 = f(3); //3,2 g1(4); //4,3,2 g1(5); //5,3,2 g2 = f(6); //6,2 g2(7); //7,6,2 g2(8); //8,6,2
  • 17. Concept slide 9 – Closures / Scope chain / Memory considerations IV Let's take a look at what's really happening (boo-ring... sorry) 1) At function creation time, a 'hidden' reference is stored in the function to point to the CURRENT scope object, this basically becomes the start of the scope chain. 2) At function invocation a) a new object is created to become the current scope b) all local variables, function parameters, and arguments array are stored in that object (i.e. 'var' is a keyword to add new members to the scope object) c) the new object gets the hidden link to point to the function's scope chain d) when end of the function is reached, the scope object gets destroyed, all local variables it carries are removed (yeah, garbage collection!) 3) IF an inner function is persisted (returned or assigned to a global object), then the 'hidden link' to the current scope is also persisted, and since ref count is not zero, the scope object (and ALL its local variables) are NOT garbage collected
  • 18. Concept slide 10 – to closure or not to closure? I function setup(obj) { var someVar = 'bla'; obj.count = 0; obj.aMethod = function() { this.count++; } } o1 = {}; setup(o1); o2 = {}; setup(o2); Good or bad? alert( o1.aMethod === o2.aMethod ); // false
  • 19. Concept slide 11 – to closure or not to closure? II function _method() { this.count++; } function setup(obj) { var someVar = 'bla'; obj.count = 0; obj.aMethod = _method; } o1 = {}; setup(o1); o2 = {}; setup(o2); alert( o1.aMethod === o2.aMethod ); // true
  • 20. Putting it all together – private scopes (function(){ var DOMAIN = 'http://www.mig33.com'; getURL = function(path) { return DOMAIN + path; } })(); url = getURL('/about-us/jobs'); alert(url);
  • 21. Putting it all together – Classes with private statics (function(){ // private static var prefix = 'M33_WIDGET_'; var count = 0; var domain = 'http://www.mig33.com'; MyClass = function() { this.id = prefix + (++count); }; o = MyClass.prototype; o.method1 = function(path) { /* … */ }; })(); m = new MyClass(); alert( m.id );
  • 22. Putting it all together – Instance privates (CrockFord style) function Foo(blarg) { var self = this; // Capture self-ref in closure this.datum = blarg; var private_data = "whatever"; // Captured in closure this.standard_method = function() { return this.datum; }; function private_method() { self.datum += 1; // Accesses member via closure return private_data; // Accesses closure } this.privileged_method = function() { private_data += "!"; // Accesses closure return private_method(); }; } o = new Foo(5); o.privileged_method(); alert( o.bar() ); alert( o.private_data ); // undefined
  • 23. Putting it all together – Classes with scopes, My own practice Enclosing closure for each class definition => allow for private static vars and methods Naming convention on instance private vars and methods (pragmatic, saves memory, easier to test) Enclosing closure for each namespace.
  • 24. Whatever – Recursion and scope chain I function factorial(n) { if (n < 2) return 1; return n * factorial(n-1); } Math.factorial = factorial; alert( Math.factorial(5) ); // 120 // later in code factorial = function(n) { return 1; } alert( Math.factorial(5) ); // 5
  • 25. Whatever – Recursion and scope chain II function factorial(n) { if (n < 2) return 1; return n * arguments.callee(n-1); } Math.factorial = factorial; alert( Math.factorial(5) ); // 120 // later in code factorial = function(n) { return 1; } alert( Math.factorial(5) ); // 120
  • 26. Whatever – Arguments.callee for function static variables function click() { if (--arguments.callee.tries < 0) { alert('forbidden'); return false; } alert('click'); return true; } click.tries = 3; click(); // click click(); // click click(); // click click(); // forbidden
  • 27. Function class – Function.apply / Function.call I Function.apply and function.call are used to manually set the meaning of 'this' function getX(y, z) { alert( [this.x, y, z] ); } o1 = {x:5}; o2 = {x:6}; getX.apply(o1, [6, 7]); getX.apply(o2, [7, 8]); getX.call(o1, 6, 7); getX.call(o2, 7, 8);
  • 28. Function class – Function.apply / Function.call II variable length arguments are typically not known in advance, use function.apply to pass an array that will translate to arguments function average () { if (arguments.length <= 0) return 0; var total = 0; for (var i=0; i<arguments.length; i++) { total += arguments[i]; } return total / arguments.length; } data = [3, 5, 7, 9, 11, 8, 2]; a = average.apply(null, data); alert(a); // 6.428571428571429
  • 29. Delegation I function MyClass(name){ this.name = name; this.setup(); } MyClass.prototype.setup = function() { var b = document.getElementsByTagName('body')[0]; b.onclick = this.sayMyName; } MyClass.prototype.sayMyName = function() { alert( this.name ); } m = new MyClass('tim'); // click in browser => undefined!
  • 30. Delegation II – Store a reference to 'this' in the closure function MyClass(name) { this.name = name; this.setup(); } MyClass.prototype.setup = function() { var b = document.getElementsByTagName('body')[0]; var self = this; b.onclick = function(){ self.sayMyName(); } } MyClass.prototype.sayMyName = function(){ alert( this.name ); } m = new MyClass('tim'); // click in browser => tim!
  • 31. Delegation III – use a helper function with function reference delegate = function(obj, func) { return function() { return func.apply(obj, arguments); } } o1 = { name: 'o1', sayMyName: function(a){ alert(a + ' ' + this.name) } }; o2 = {name: 'o2'}; o2.sayIt = delegate(o1, o1.sayMyName); o2.sayIt('hello');
  • 32. Delegation IV – use a helper function with a function name delegate = function(obj, funcName) { return function() { return obj[funcName].apply(obj, arguments); } } o1 = { name: 'o1', sayMyName: function(a){ alert(a + ' ' + this.name) } }; o2 = {name: 'o2'}; o2.sayIt = delegate(o1, 'sayMyName'); o2.sayIt('hello'); // 'hello o1'
  • 33. Delegation V – allow setting fixed parameters, when delegating delegate = function(obj, funcName, greeting) { return function() { return obj[funcName].apply(obj, [greeting]); } } o1 = { name: 'o1', sayMyName: function(a){ alert(a + ' ' + this.name) } }; o2 = {name: 'o2'}; o2.sayIt = delegate(o1, 'sayMyName', 'bonjour'); o2.sayIt('hello'); // 'bonjour o1'
  • 34. Trivia I In a browser, the global scope is the window object itself :) a = 5; alert( window.a ); // 5
  • 35. Trivia II - Assignment without explicit scope Assignment without explicit scope is done to the first scope object that had the variable declared locally, or global scope if none: var x = 5; function foo() { x = 6; } foo(); alert(x); // 6 /*======================================*/ var x = 5; function foo() { var x; return function() { x = 6; } } foo()(); alert(x); // 5
  • 36. Conclusion Functions in JS are VERY powerful Closures are probably the most useful feature of JS Beware, you can get bitten hard, especially with long closures (e.g. jQuery has one fat outer function scope of 6,500+ lines). Watch out for: ●local variables in outer scopes that are left alive forever ●function duplication where they are not required Especially true in the days of cool ajaxy libraries like jQuery or ExtJS, which make it very easy to use closures without completely understanding them. I'm not bashing jQuery, I looove jQuery, just know your tools well! :D