KEMBAR78
Workshop 1: Good practices in JavaScript | PPTX
Front End Workshops
II. (Not so) Basic JavaScript
concepts
Mario García Martín
mgarcia@visual-engin.com
Good practices in JavaScript
“Always code as if the guy who ends up maintaining your code will
be a violent psychopath who knows where you live.”
— John Woods
Avoid global variables
// homer.js
var isDrunk = true;
// bart.js
var isDrunk = false;
// index.html
<script src=”./homer.js”></script>
<script src=”./bart.js”></script>
console.log(isDrunk);
Global variables and functions can be overwritten by other
scripts.
Declare variables with var
Using ‘use strict’ directive will prevent undeclared variable
definitions.
function defineBeer() {
beer = 1;
}
defineBeer();
Not doing so results in global variable declaration.
'use strict';
function defineBeer() {
beer = 1;
}
defineBeer();
Uncaught ReferenceError: beer is
not defined
function defineBeer() {
var beer = 1;
}
defineBeer();
Manipulating the DOM
$('#homer).addClass('alcoholic');
// Some logic here...
$('#homer').addClass('angry');
Writing the DOM
Reading the DOM
var $homer = $('#homer');
$homer.addClass('alcoholic');
// Some logic here...
$homer.addClass('angry');
var $ul = $('#target-ul');
for (var i=0; i<4; i++) {
$ul.append('<li>' + i +
'</li>');
}
var html = '';
for (var i=0; i<4; i++) {
html += '<li>' + i + '</li>';
}
$('#target-ul').append(html);
Avoid heavy nesting
function logHomerBehaviour(homer) {
if (homer.isAtWork()) {
for (var i=0; i<4; i++) {
if (homer.isAsleep()) {
if (homer.isSnoring()) {
for (var j=0; j<2; j++) {
snore += 'Zz...';
}
console.log(snore);
}
} else {
console.log('Doughnuts!');
}
}
}
}
function logHomerBehaviour(homer) {
if (!homer.isAtWork()) { return; }
for (var i=0; i<4; i++) {
if (homer.isAsleep()) {
logHomerSleeping(homer);
} else {
console.log('Doughnuts!');
}
}
}
function logHomerSleeping(homer) {
if (!homer.isSnoring()) { return; }
console.log('Zz...Zz...');
}
Comment your code
“Good code explains itself”.
function handleEvent(ev) {
// In IE9 and earlier, use the window.event.
ev = ev || window.event;
}
Comment what you consider needed, but don’t tell others
your life story.
Comment your code
“Good code explains itself”.
function handleEvent(ev) {
// In IE9 and earlier, use the window.event.
ev = ev || window.event;
}
Comment what you consider needed, but don’t tell others
your life story.
Other good practices
Avoid eval function
Never pass a string to setTimeout or setInterval
Use === instead of ==
console.log(0 == false); // true
console.log('2' == 2); // true
console.log(0 === false); // false
console.log('2' === 2); // false
Tools: JS Lint
The only valid measurement of code quality...
WTFs/minute
More information in...
● http://www.slideshare.net/cheilmann/javascript-best-practices-1041724
● https://www.youtube.com/watch?v=hQVTIJBZook
● https://www.devbridge.com/articles/javascript-best-practices/
● http://www.codeproject.com/Articles/580165/JavaScript-Best-Practices
(Ir)Regular expressions
“Some people, when confronted with a problem, think ‘I know, I’ll
use regular expressions.’ Now they have two problems.”
— Jamie Zawinski
Creating a regular expression
var regexp1 = new RegExp('abc', 'gi');
var regexp2 = /abc/gi;
/abc/ A sequence of characters
/[abc]/ Any character from a set of characters
/[^abc]/ Any character not in a set of characters
/[0-9]/ Any character in a range of characters
/x+/ One or more occurrences of pattern x
/x*/ Zero or more occurrences
/x?/ Zero or one occurrence
/x{2,4}/ Between two and four occurrences
/(abc)/ A group
/a|b|c/ Any one of several patterns
/d/ Any digit character
/w/ An alphanumeric character [a-zA-Z0-9_]
/s/ Any whitespace character
/./ Any character except newlines
/^/ Start of input
/$/ End of input
Using a regular expression in JavaScript
/[0-9]/.test('in 1992'); //true
var neighbor = /neighbou?r/;
neighbor.test('neighbour'); // true
neighbor.test('neighbor'); // true
Through the RexExp object
Through the String object
'12345'.match(/(d)(d)+/); // ['12345', '1', '5']
'Homer drinks beer'.search(/beer/); // 13
'Ho+me[]r'.replace(/[^ws]/g, ''); // 'Homer'
'Homer drinks beer'.split(/s/); // ['Homer', 'drinks', 'beer']
var match = /d+/.exec('one two 100');
console.log(match); // ['100']
console.log(match.index); // 8
Do not abuse regular expressions...
^(?:(?:(?:0?[13578]|1[02])(/|-)31)|(?:(?:0?[1,3-9]|1[0-2])(/|-
)(?:29|30)))(/|-)(?:[1-9]ddd|d[1-9]dd|dd[1-9]d|ddd[1-
9])$|^(?:(?:0?[1-9]|1[0-2])(/|-)(?:0?[1-9]|1d|2[0-8]))(/|-)(?:[1-
9]ddd|d[1-9]dd|dd[1-9]d|ddd[1-9])$|^(0?2(/|-)29)(/|-
)(?:(?:0[48]00|[13579][26]00|[2468][048]00)|(?:20)?(?:0[48]|[2468][048]|[13579][
26]))$
More information in...
● Mastering Regular Expressions, by Jeffrey E.F. Friedl
● Introducing Regular Expressions, by Michael Fitzgerald
● Regular Expressions Cookbook, by Jan Goyvaerts and Steven Levithan
● https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/Regular_E
xpressions
● http://eloquentjavascript.net/09_regexp.html
● http://www.cheatography.com/davechild/cheat-sheets/regular-
expressions/
Scopes and Closures. Prototype
“First learn computer science and all the theory. Next develop a
programming style. Then forget all that and just hack.”
— George Carrette
Lexical scope
In JavaScript, scopes are declared by functions, not by
blocks.
// Global scope
if (true) {
var x =
24;
}
console.log(x);
var x;
if (true) {
x = 24;
}
console.log(x);
Hoisting
Lexical scope
var hero = aHero();
var newSaga = function() {
var foil = aFoil();
var saga = function() {
var deed = aDeed();
console.log(hero + deed + foil);
}
}
Execution context (in-memory scope)
var hero = randStr();
var newSaga = function() {
var foil = randStr();
var saga = function() {
var deed = randStr();
console.log(hero + deed + foil);
}
saga();
saga();
}
newSaga();
newSaga();
hero = ‘gal’
newSaga = [ Function ]
foil = ‘cow’
saga = [ Function ]
deed = ‘eyes’
foil = ‘cow’
saga = [ Function ]
Execution context (in-memory scope)
var hero = randStr();
var newSaga = function() {
var foil = randStr();
var saga = function() {
var deed = randStr();
console.log(hero + deed + foil);
}
saga();
saga();
}
newSaga();
newSaga();
hero = ‘gal’
newSaga = [ Function ]
foil = ‘cow’
saga = [ Function ]
foil = ‘cow’
saga = [ Function ]
deed = ‘tips’
Execution context (in-memory scope)
var hero = randStr();
var newSaga = function() {
var foil = randStr();
var saga = function() {
var deed = randStr();
console.log(hero + deed + foil);
}
saga();
saga();
}
newSaga();
newSaga();
hero = ‘gal’
newSaga = [ Function ]
foil = ‘cow’
saga = [ Function ]
foil = ‘cat’
saga = [ Function ]
deed = ‘Rubs’
Execution context (in-memory scope)
var hero = randStr();
var newSaga = function() {
var foil = randStr();
var saga = function() {
var deed = randStr();
console.log(hero + deed + foil);
}
saga();
saga();
}
newSaga();
newSaga();
hero = ‘gal’
newSaga = [ Function ]
foil = ‘cow’
saga = [ Function ]
foil = ‘cat’
saga = [ Function ]
deed = ‘Robs’
‘this’ keyword
Invocation as a method
var homer = {
beer: 'Nice to have another one!',
info: function() {
console.log(this === homer);
console.log(this.beer);
}
};
homer.info(); // true, 'Nice to have another one!'
var bart = {
beer: 'Too young'
};
bart.info = homer.info;
bart.info(); // false, 'Too young'
function bar() {
console.log(this);
}
bar(); // global
‘this’ keyword
Invocation as a method
var anum = 0;
var foo = {
anum: 10,
baz: {
anum: 20,
bar: function() {
console.log(this.anum);
}
}
}
foo.baz.bar(); // 20
var hello = foo.baz.bar;
hello(); // 0
var foo = {
baz: function() {
console.log(this);
}
}
foo.baz(); // foo
var anotherBaz = foo.baz;
anotherBaz(); // global
‘this’ keyword
Invocation as a constructor
function Person() {
this.x = 0;
}
var person = new Person();
console.log(person.x); // 0
‘this’ keyword
Invocation with the apply and call methods
function juggle() {
var result = 0;
for (var n = 0; n < arguments.length; n++) {
result += arguments[n];
}
this.result = result;
}
var ninja1 = {};
var ninja2 = {};
juggle.apply(ninja1, [1, 2, 3, 4]); // ninja1.result = 10;
juggle.call(ninja2, 5, 6, 7, 8); // ninja2.result = 26;
Closures
Combines two things: a function, and the environment in which that function
was created.
var toast = 'Cheers!';
function makeToast() {
console.log(toast);
}
makeToast();
function
makeToast() { ... }
var toast
Closures
var scope = 'global scope';
function checkscope() {
var scope = 'local scope';
function f() { return
scope; }
return f();
}
checkscope(); // 'local scope';
var scope = 'global scope';
function checkscope() {
var scope = 'local scope';
function f() { return
scope; }
return f;
}
var func = checkscope();
func(); // 'local scope';
Closures
var fns = [];
for (var i=0; i<4; i++) {
fns.push(function() {
console.log(i);
});
}
fns[0](); // 4
fns[1](); // 4
fns[2](); // 4
fns[3](); // 4
var fns = [];
for (var i=0; i<4; i++) {
fns.push( (function(a) {
return function() {
console.log(a);
};
})(i) );
}
fns[0](); // 0
fns[1](); // 1
fns[2](); // 2
fns[3](); // 3
Constructor function
function Animal(_name) {
var name = _name;
this.getName = function() {
console.log('My name is ' + name);
};
this.setName = function(_name) {
name = _name;
};
}
var animal = new Animal('Santa');
animal.getName(); // My name is Santa
animal.setName('New Santa');
animal.getName(); // My name is New Santa
Prototype chain
var o = { a: 1 };
// o --> Object.prototype --> null
var a = ['Homer', 'Marge', 'Lisa'];
// a --> Array.prototype --> Object.prototype --> null
function f() { return 2; }
// f --> Function.prototype --> Object.prototype --> null
Prototype chain
function Animal(_name) {
// Instance properties can be set on each instance of the class
this.name = _name;
}
// Prototype properties are shared across all instances of the class.
Animal.prototype.getName = function() {
console.log('My name is ' + this.name);
};
var animal = new Animal('Santa');
animal.getName(); // My name is Santa
Inheritance
function Cat(_name) {
Animal.call(this, _name);
}
Cat.prototype = new Animal();
Cat.prototype.scratch = function() {
console.log('I love to scratch!');
}
var cat = new Cat('Claws');
cat.getName(); // My name is Claws
cat.scratch(); // I love to scratch!
More information in...
● Secrets of the JavaScript Ninja, by John Resig
● Javascript, the definitive guide, by David Flanagan
● Scope & closures, by Kyle Simpson
● http://www.sitepoint.com/demystifying-javascript-variable-scope-
hoisting/
● http://davidshariff.com/blog/what-is-the-execution-context-in-
javascript/
● http://davidshariff.com/blog/javascript-scope-chain-and-closures/
● http://davidshariff.com/blog/javascript-this-keyword/
Memory leaks
“‘Yeah, it works but you’re leaking memory everywhere. Perhaps
we should fix that”. I’ll just restart apache every 10 requests.”
— Rasmus Lerdorf
Circular references
<div id="target">Element</div>
<script type="text/javascript">
var obj = document.getElementById('target');
document.getElementById('target').property = obj;
obj.bigString = new Array(10000).join('*');
</script>
Example 1
Circular references
<div id="target"></div>
<script type="text/javascript">
function myFunction(element) {
this.elementReference = element;
element.property = this;
}
function leak() {
new myFunction(document.getElementById('target'));
}
leak();
</script>
Example 2
Closures and circular references
<button id="element">Click Me</button>
<script type="text/javascript">
function outerFunction() {
var obj = document.getElementById('element');
obj.onclick = function innerFunction() {
console.log('Hi! I will leak');
};
obj.bigString = new Array(10000).join('*');
};
outerFunction();
</script>
Closures. Break the circular reference
<button id="element">Click Me</button>
<script type="text/javascript">
function outerFunction() {
var obj = document.getElementById('element');
obj.onclick = function innerFunction() {
console.log('Hi! I have avoided the leak');
};
obj.bigString = new Array(10000).join('*'));
obj = null; //This breaks the circular reference
};
outerFunction();
</script>
Closures. Add another closure
<button id="element">Click Me</button>
<script type="text/javascript">
function outerFunction() {
var anotherObj = function innerFunction() {
console.log('Hi! I have avoided the leak');
};
(function anotherInnerFunction() {
var obj = document.getElementById('element');
obj.onclick = anotherObj;
})();
};
outerFunction();
</script>
Closures. Avoid the initial closure
<button id="element">Click Me</button>
<script type="text/javascript">
function outerFunction() {
var obj = document.getElementById('element');
obj.onclick = doesNotLeak;
}
function doesNotLeak() {
console.log('Hi! I have avoided the leak');
}
outerFunction();
</script>
More information in...
● https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Memory_Management
● http://www.ibm.com/developerworks/web/library/wa-memleak/
● https://msdn.microsoft.com/en-us/magazine/ff728624.aspx
Thanks for your attention!
Leave your questions on the comments section
Workshop 1: Good practices in JavaScript

Workshop 1: Good practices in JavaScript

  • 1.
    Front End Workshops II.(Not so) Basic JavaScript concepts Mario García Martín mgarcia@visual-engin.com
  • 2.
    Good practices inJavaScript “Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.” — John Woods
  • 3.
    Avoid global variables //homer.js var isDrunk = true; // bart.js var isDrunk = false; // index.html <script src=”./homer.js”></script> <script src=”./bart.js”></script> console.log(isDrunk); Global variables and functions can be overwritten by other scripts.
  • 4.
    Declare variables withvar Using ‘use strict’ directive will prevent undeclared variable definitions. function defineBeer() { beer = 1; } defineBeer(); Not doing so results in global variable declaration. 'use strict'; function defineBeer() { beer = 1; } defineBeer(); Uncaught ReferenceError: beer is not defined function defineBeer() { var beer = 1; } defineBeer();
  • 5.
    Manipulating the DOM $('#homer).addClass('alcoholic'); //Some logic here... $('#homer').addClass('angry'); Writing the DOM Reading the DOM var $homer = $('#homer'); $homer.addClass('alcoholic'); // Some logic here... $homer.addClass('angry'); var $ul = $('#target-ul'); for (var i=0; i<4; i++) { $ul.append('<li>' + i + '</li>'); } var html = ''; for (var i=0; i<4; i++) { html += '<li>' + i + '</li>'; } $('#target-ul').append(html);
  • 6.
    Avoid heavy nesting functionlogHomerBehaviour(homer) { if (homer.isAtWork()) { for (var i=0; i<4; i++) { if (homer.isAsleep()) { if (homer.isSnoring()) { for (var j=0; j<2; j++) { snore += 'Zz...'; } console.log(snore); } } else { console.log('Doughnuts!'); } } } } function logHomerBehaviour(homer) { if (!homer.isAtWork()) { return; } for (var i=0; i<4; i++) { if (homer.isAsleep()) { logHomerSleeping(homer); } else { console.log('Doughnuts!'); } } } function logHomerSleeping(homer) { if (!homer.isSnoring()) { return; } console.log('Zz...Zz...'); }
  • 7.
    Comment your code “Goodcode explains itself”. function handleEvent(ev) { // In IE9 and earlier, use the window.event. ev = ev || window.event; } Comment what you consider needed, but don’t tell others your life story.
  • 8.
    Comment your code “Goodcode explains itself”. function handleEvent(ev) { // In IE9 and earlier, use the window.event. ev = ev || window.event; } Comment what you consider needed, but don’t tell others your life story.
  • 9.
    Other good practices Avoideval function Never pass a string to setTimeout or setInterval Use === instead of == console.log(0 == false); // true console.log('2' == 2); // true console.log(0 === false); // false console.log('2' === 2); // false Tools: JS Lint
  • 10.
    The only validmeasurement of code quality... WTFs/minute
  • 11.
    More information in... ●http://www.slideshare.net/cheilmann/javascript-best-practices-1041724 ● https://www.youtube.com/watch?v=hQVTIJBZook ● https://www.devbridge.com/articles/javascript-best-practices/ ● http://www.codeproject.com/Articles/580165/JavaScript-Best-Practices
  • 12.
    (Ir)Regular expressions “Some people,when confronted with a problem, think ‘I know, I’ll use regular expressions.’ Now they have two problems.” — Jamie Zawinski
  • 13.
    Creating a regularexpression var regexp1 = new RegExp('abc', 'gi'); var regexp2 = /abc/gi; /abc/ A sequence of characters /[abc]/ Any character from a set of characters /[^abc]/ Any character not in a set of characters /[0-9]/ Any character in a range of characters /x+/ One or more occurrences of pattern x /x*/ Zero or more occurrences /x?/ Zero or one occurrence /x{2,4}/ Between two and four occurrences /(abc)/ A group /a|b|c/ Any one of several patterns /d/ Any digit character /w/ An alphanumeric character [a-zA-Z0-9_] /s/ Any whitespace character /./ Any character except newlines /^/ Start of input /$/ End of input
  • 14.
    Using a regularexpression in JavaScript /[0-9]/.test('in 1992'); //true var neighbor = /neighbou?r/; neighbor.test('neighbour'); // true neighbor.test('neighbor'); // true Through the RexExp object Through the String object '12345'.match(/(d)(d)+/); // ['12345', '1', '5'] 'Homer drinks beer'.search(/beer/); // 13 'Ho+me[]r'.replace(/[^ws]/g, ''); // 'Homer' 'Homer drinks beer'.split(/s/); // ['Homer', 'drinks', 'beer'] var match = /d+/.exec('one two 100'); console.log(match); // ['100'] console.log(match.index); // 8
  • 15.
    Do not abuseregular expressions... ^(?:(?:(?:0?[13578]|1[02])(/|-)31)|(?:(?:0?[1,3-9]|1[0-2])(/|- )(?:29|30)))(/|-)(?:[1-9]ddd|d[1-9]dd|dd[1-9]d|ddd[1- 9])$|^(?:(?:0?[1-9]|1[0-2])(/|-)(?:0?[1-9]|1d|2[0-8]))(/|-)(?:[1- 9]ddd|d[1-9]dd|dd[1-9]d|ddd[1-9])$|^(0?2(/|-)29)(/|- )(?:(?:0[48]00|[13579][26]00|[2468][048]00)|(?:20)?(?:0[48]|[2468][048]|[13579][ 26]))$
  • 16.
    More information in... ●Mastering Regular Expressions, by Jeffrey E.F. Friedl ● Introducing Regular Expressions, by Michael Fitzgerald ● Regular Expressions Cookbook, by Jan Goyvaerts and Steven Levithan ● https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/Regular_E xpressions ● http://eloquentjavascript.net/09_regexp.html ● http://www.cheatography.com/davechild/cheat-sheets/regular- expressions/
  • 17.
    Scopes and Closures.Prototype “First learn computer science and all the theory. Next develop a programming style. Then forget all that and just hack.” — George Carrette
  • 18.
    Lexical scope In JavaScript,scopes are declared by functions, not by blocks. // Global scope if (true) { var x = 24; } console.log(x); var x; if (true) { x = 24; } console.log(x); Hoisting
  • 19.
    Lexical scope var hero= aHero(); var newSaga = function() { var foil = aFoil(); var saga = function() { var deed = aDeed(); console.log(hero + deed + foil); } }
  • 20.
    Execution context (in-memoryscope) var hero = randStr(); var newSaga = function() { var foil = randStr(); var saga = function() { var deed = randStr(); console.log(hero + deed + foil); } saga(); saga(); } newSaga(); newSaga(); hero = ‘gal’ newSaga = [ Function ] foil = ‘cow’ saga = [ Function ] deed = ‘eyes’ foil = ‘cow’ saga = [ Function ]
  • 21.
    Execution context (in-memoryscope) var hero = randStr(); var newSaga = function() { var foil = randStr(); var saga = function() { var deed = randStr(); console.log(hero + deed + foil); } saga(); saga(); } newSaga(); newSaga(); hero = ‘gal’ newSaga = [ Function ] foil = ‘cow’ saga = [ Function ] foil = ‘cow’ saga = [ Function ] deed = ‘tips’
  • 22.
    Execution context (in-memoryscope) var hero = randStr(); var newSaga = function() { var foil = randStr(); var saga = function() { var deed = randStr(); console.log(hero + deed + foil); } saga(); saga(); } newSaga(); newSaga(); hero = ‘gal’ newSaga = [ Function ] foil = ‘cow’ saga = [ Function ] foil = ‘cat’ saga = [ Function ] deed = ‘Rubs’
  • 23.
    Execution context (in-memoryscope) var hero = randStr(); var newSaga = function() { var foil = randStr(); var saga = function() { var deed = randStr(); console.log(hero + deed + foil); } saga(); saga(); } newSaga(); newSaga(); hero = ‘gal’ newSaga = [ Function ] foil = ‘cow’ saga = [ Function ] foil = ‘cat’ saga = [ Function ] deed = ‘Robs’
  • 24.
    ‘this’ keyword Invocation asa method var homer = { beer: 'Nice to have another one!', info: function() { console.log(this === homer); console.log(this.beer); } }; homer.info(); // true, 'Nice to have another one!' var bart = { beer: 'Too young' }; bart.info = homer.info; bart.info(); // false, 'Too young' function bar() { console.log(this); } bar(); // global
  • 25.
    ‘this’ keyword Invocation asa method var anum = 0; var foo = { anum: 10, baz: { anum: 20, bar: function() { console.log(this.anum); } } } foo.baz.bar(); // 20 var hello = foo.baz.bar; hello(); // 0 var foo = { baz: function() { console.log(this); } } foo.baz(); // foo var anotherBaz = foo.baz; anotherBaz(); // global
  • 26.
    ‘this’ keyword Invocation asa constructor function Person() { this.x = 0; } var person = new Person(); console.log(person.x); // 0
  • 27.
    ‘this’ keyword Invocation withthe apply and call methods function juggle() { var result = 0; for (var n = 0; n < arguments.length; n++) { result += arguments[n]; } this.result = result; } var ninja1 = {}; var ninja2 = {}; juggle.apply(ninja1, [1, 2, 3, 4]); // ninja1.result = 10; juggle.call(ninja2, 5, 6, 7, 8); // ninja2.result = 26;
  • 28.
    Closures Combines two things:a function, and the environment in which that function was created. var toast = 'Cheers!'; function makeToast() { console.log(toast); } makeToast(); function makeToast() { ... } var toast
  • 29.
    Closures var scope ='global scope'; function checkscope() { var scope = 'local scope'; function f() { return scope; } return f(); } checkscope(); // 'local scope'; var scope = 'global scope'; function checkscope() { var scope = 'local scope'; function f() { return scope; } return f; } var func = checkscope(); func(); // 'local scope';
  • 30.
    Closures var fns =[]; for (var i=0; i<4; i++) { fns.push(function() { console.log(i); }); } fns[0](); // 4 fns[1](); // 4 fns[2](); // 4 fns[3](); // 4 var fns = []; for (var i=0; i<4; i++) { fns.push( (function(a) { return function() { console.log(a); }; })(i) ); } fns[0](); // 0 fns[1](); // 1 fns[2](); // 2 fns[3](); // 3
  • 31.
    Constructor function function Animal(_name){ var name = _name; this.getName = function() { console.log('My name is ' + name); }; this.setName = function(_name) { name = _name; }; } var animal = new Animal('Santa'); animal.getName(); // My name is Santa animal.setName('New Santa'); animal.getName(); // My name is New Santa
  • 32.
    Prototype chain var o= { a: 1 }; // o --> Object.prototype --> null var a = ['Homer', 'Marge', 'Lisa']; // a --> Array.prototype --> Object.prototype --> null function f() { return 2; } // f --> Function.prototype --> Object.prototype --> null
  • 33.
    Prototype chain function Animal(_name){ // Instance properties can be set on each instance of the class this.name = _name; } // Prototype properties are shared across all instances of the class. Animal.prototype.getName = function() { console.log('My name is ' + this.name); }; var animal = new Animal('Santa'); animal.getName(); // My name is Santa
  • 34.
    Inheritance function Cat(_name) { Animal.call(this,_name); } Cat.prototype = new Animal(); Cat.prototype.scratch = function() { console.log('I love to scratch!'); } var cat = new Cat('Claws'); cat.getName(); // My name is Claws cat.scratch(); // I love to scratch!
  • 35.
    More information in... ●Secrets of the JavaScript Ninja, by John Resig ● Javascript, the definitive guide, by David Flanagan ● Scope & closures, by Kyle Simpson ● http://www.sitepoint.com/demystifying-javascript-variable-scope- hoisting/ ● http://davidshariff.com/blog/what-is-the-execution-context-in- javascript/ ● http://davidshariff.com/blog/javascript-scope-chain-and-closures/ ● http://davidshariff.com/blog/javascript-this-keyword/
  • 36.
    Memory leaks “‘Yeah, itworks but you’re leaking memory everywhere. Perhaps we should fix that”. I’ll just restart apache every 10 requests.” — Rasmus Lerdorf
  • 37.
    Circular references <div id="target">Element</div> <scripttype="text/javascript"> var obj = document.getElementById('target'); document.getElementById('target').property = obj; obj.bigString = new Array(10000).join('*'); </script> Example 1
  • 38.
    Circular references <div id="target"></div> <scripttype="text/javascript"> function myFunction(element) { this.elementReference = element; element.property = this; } function leak() { new myFunction(document.getElementById('target')); } leak(); </script> Example 2
  • 39.
    Closures and circularreferences <button id="element">Click Me</button> <script type="text/javascript"> function outerFunction() { var obj = document.getElementById('element'); obj.onclick = function innerFunction() { console.log('Hi! I will leak'); }; obj.bigString = new Array(10000).join('*'); }; outerFunction(); </script>
  • 40.
    Closures. Break thecircular reference <button id="element">Click Me</button> <script type="text/javascript"> function outerFunction() { var obj = document.getElementById('element'); obj.onclick = function innerFunction() { console.log('Hi! I have avoided the leak'); }; obj.bigString = new Array(10000).join('*')); obj = null; //This breaks the circular reference }; outerFunction(); </script>
  • 41.
    Closures. Add anotherclosure <button id="element">Click Me</button> <script type="text/javascript"> function outerFunction() { var anotherObj = function innerFunction() { console.log('Hi! I have avoided the leak'); }; (function anotherInnerFunction() { var obj = document.getElementById('element'); obj.onclick = anotherObj; })(); }; outerFunction(); </script>
  • 42.
    Closures. Avoid theinitial closure <button id="element">Click Me</button> <script type="text/javascript"> function outerFunction() { var obj = document.getElementById('element'); obj.onclick = doesNotLeak; } function doesNotLeak() { console.log('Hi! I have avoided the leak'); } outerFunction(); </script>
  • 43.
    More information in... ●https://developer.mozilla.org/en- US/docs/Web/JavaScript/Memory_Management ● http://www.ibm.com/developerworks/web/library/wa-memleak/ ● https://msdn.microsoft.com/en-us/magazine/ff728624.aspx
  • 44.
    Thanks for yourattention! Leave your questions on the comments section