SlideShare a Scribd company logo
1 of 36
Download to read offline
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

What's hot

What's hot (20)

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

Viewers also liked (7)

P grey kotlerdeliveringvalue
P grey kotlerdeliveringvalueP grey kotlerdeliveringvalue
P grey kotlerdeliveringvalue
 
Introduction to Client-Side Javascript
Introduction to Client-Side JavascriptIntroduction to Client-Side Javascript
Introduction to Client-Side Javascript
 
Code for kombol - Objects and Functions in JS and NodeJS
Code for kombol - Objects and Functions in JS and NodeJSCode for kombol - Objects and Functions in JS and NodeJS
Code for kombol - Objects and Functions in JS and NodeJS
 
Javascript: master this
Javascript: master thisJavascript: master this
Javascript: master this
 
Js ppt
Js pptJs ppt
Js ppt
 
2015 Upload Campaigns Calendar - SlideShare
2015 Upload Campaigns Calendar - SlideShare2015 Upload Campaigns Calendar - SlideShare
2015 Upload Campaigns Calendar - SlideShare
 
What to Upload to SlideShare
What to Upload to SlideShareWhat to Upload to SlideShare
What to Upload to SlideShare
 

Similar to The mighty js_function

JavaScript Growing Up
JavaScript Growing UpJavaScript Growing Up
JavaScript Growing Up
David Padbury
 

Similar to The mighty js_function (20)

Ten useful JavaScript tips & best practices
Ten useful JavaScript tips & best practicesTen useful JavaScript tips & best practices
Ten useful JavaScript tips & best practices
 
Code Generation in PHP - PHPConf 2015
Code Generation in PHP - PHPConf 2015Code Generation in PHP - PHPConf 2015
Code Generation in PHP - PHPConf 2015
 
Advanced JavaScript
Advanced JavaScriptAdvanced JavaScript
Advanced JavaScript
 
JavaScript Closures for Dummies & JavaScript prototype, closures and OOP.
JavaScript Closures for Dummies & JavaScript prototype, closures and OOP.JavaScript Closures for Dummies & JavaScript prototype, closures and OOP.
JavaScript Closures for Dummies & JavaScript prototype, closures and OOP.
 
LISA QooxdooTutorial Slides
LISA QooxdooTutorial SlidesLISA QooxdooTutorial Slides
LISA QooxdooTutorial Slides
 
Workshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScriptWorkshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScript
 
Object Oriented JavaScript
Object Oriented JavaScriptObject Oriented JavaScript
Object Oriented JavaScript
 
Es6 hackathon
Es6 hackathonEs6 hackathon
Es6 hackathon
 
Workshop 10: ECMAScript 6
Workshop 10: ECMAScript 6Workshop 10: ECMAScript 6
Workshop 10: ECMAScript 6
 
Say It With Javascript
Say It With JavascriptSay It With Javascript
Say It With Javascript
 
ES6 PPT FOR 2016
ES6 PPT FOR 2016ES6 PPT FOR 2016
ES6 PPT FOR 2016
 
Sane Async Patterns
Sane Async PatternsSane Async Patterns
Sane Async Patterns
 
Node.js System: The Landing
Node.js System: The LandingNode.js System: The Landing
Node.js System: The Landing
 
Advanced JavaScript
Advanced JavaScript Advanced JavaScript
Advanced JavaScript
 
JavaScript Growing Up
JavaScript Growing UpJavaScript Growing Up
JavaScript Growing Up
 
JavaScript Functions
JavaScript FunctionsJavaScript Functions
JavaScript Functions
 
JavaScript - i och utanför webbläsaren (2010-03-03)
JavaScript - i och utanför webbläsaren (2010-03-03)JavaScript - i och utanför webbläsaren (2010-03-03)
JavaScript - i och utanför webbläsaren (2010-03-03)
 
EcmaScript 6
EcmaScript 6 EcmaScript 6
EcmaScript 6
 
ESCMAScript 6: Get Ready For The Future. Now
ESCMAScript 6: Get Ready For The Future. NowESCMAScript 6: Get Ready For The Future. Now
ESCMAScript 6: Get Ready For The Future. Now
 
"let ECMAScript = 6"
"let ECMAScript = 6" "let ECMAScript = 6"
"let ECMAScript = 6"
 

Recently uploaded

IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
Enterprise Knowledge
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
Earley Information Science
 

Recently uploaded (20)

presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 

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