+ All Categories
Home > Software > Workshop 1: Good practices in JavaScript

Workshop 1: Good practices in JavaScript

Date post: 14-Jan-2017
Category:
Upload: visual-engineering
View: 524 times
Download: 2 times
Share this document with a friend
45
Front End Workshops II.(Not so) Basic JavaScript concepts Mario García Martín [email protected]
Transcript
Page 1: Workshop 1: Good practices in JavaScript

Front End WorkshopsII. (Not so) Basic JavaScript

concepts

Mario García Martí[email protected]

Page 2: Workshop 1: Good practices in JavaScript

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

Page 3: Workshop 1: Good practices in JavaScript

Avoid global variables

// homer.jsvar isDrunk = true;

// bart.jsvar 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.

Page 4: Workshop 1: Good practices in JavaScript

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();

Page 5: Workshop 1: Good practices in JavaScript

Manipulating the DOM

$('#homer).addClass('alcoholic');// Some logic here...$('#homer').addClass('angry');

Writing the DOM

Reading the DOMvar $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);

Page 6: Workshop 1: Good practices in JavaScript

Avoid heavy nestingfunction 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...');}

Page 7: Workshop 1: Good practices in JavaScript

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.

Page 8: Workshop 1: Good practices in JavaScript

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.

Page 9: Workshop 1: Good practices in JavaScript

Other good practices

Avoid eval functionNever pass a string to setTimeout or setInterval

Use === instead of ==console.log(0 == false); // trueconsole.log('2' == 2); // true

console.log(0 === false); // falseconsole.log('2' === 2); // false

Tools: JS Lint

Page 10: Workshop 1: Good practices in JavaScript

The only valid measurement of code quality...

WTFs/minute

Page 11: Workshop 1: Good practices in JavaScript

More information in...● http://www.slideshare.net/cheilmann/javascript-best-practices-1

041724

● https://www.youtube.com/watch?v=hQVTIJBZook

● https://www.devbridge.com/articles/javascript-best-practices/

● http://www.codeproject.com/Articles/580165/JavaScript-Best-Practices

Page 12: Workshop 1: Good practices in JavaScript

(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

Page 13: Workshop 1: Good practices in JavaScript

Creating a regular expressionvar 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

Page 14: Workshop 1: Good practices in JavaScript

Using a regular expression in JavaScript

/[0-9]/.test('in 1992'); //true

var neighbor = /neighbou?r/;neighbor.test('neighbour'); // trueneighbor.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(/[^\w\s]/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

Page 15: Workshop 1: Good practices in JavaScript

Do not abuse regular expressions...

^(?:(?:(?:0?[13578]|1[02])(\/|-)31)|(?:(?:0?[1,3-9]|1[0-2])(\/|-)(?:29|

30)))(\/|-)(?:[1-9]\d\d\d|\d[1-9]\d\d|\d\d[1-9]\d|\d\d\d[1-9])$|^(?:(?:0?

[1-9]|1[0-2])(\/|-)(?:0?[1-9]|1\d|2[0-8]))(\/|-)(?:[1-9]\d\d\d|\d[1-9]\d\

d|\d\d[1-9]\d|\d\d\d[1-9])$|^(0?2(\/|-)29)(\/|-)(?:(?:0[48]00|[13579]

[26]00|[2468][048]00)|(?:20)?(?:0[48]|[2468][048]|[13579][26]))$

Page 16: Workshop 1: Good practices in JavaScript

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/Re

gular_Expressions● http://eloquentjavascript.net/09_regexp.html● http://www.cheatography.com/davechild/cheat-sheets/regular-

expressions/

Page 17: Workshop 1: Good practices in JavaScript

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

Page 18: Workshop 1: Good practices in JavaScript

Lexical scopeIn 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

Page 19: Workshop 1: Good practices in JavaScript

Lexical scopevar hero = aHero();

var newSaga = function() {

var foil = aFoil();

var saga = function() {

var deed = aDeed();

console.log(hero + deed + foil);

}

}

Page 20: Workshop 1: Good practices in JavaScript

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 ]

Page 21: Workshop 1: Good practices in JavaScript

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’

Page 22: Workshop 1: Good practices in JavaScript

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’

Page 23: Workshop 1: Good practices in JavaScript

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’

Page 24: Workshop 1: Good practices in JavaScript

‘this’ keywordInvocation 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

Page 25: Workshop 1: Good practices in JavaScript

‘this’ keywordInvocation as a method var anum = 0;

var foo = { anum: 10, baz: { anum: 20, bar: function() { console.log(this.anum); } }}foo.baz.bar(); // 20var hello = foo.baz.bar;hello(); // 0

var foo = { baz: function() { console.log(this); }}foo.baz(); // foo

var anotherBaz = foo.baz;anotherBaz(); // global

Page 26: Workshop 1: Good practices in JavaScript

‘this’ keywordInvocation as a constructor

function Person() {this.x = 0;

}

var person = new Person();console.log(person.x); // 0

Page 27: Workshop 1: Good practices in JavaScript

‘this’ keywordInvocation with the apply and call methodsfunction 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;

Page 28: Workshop 1: Good practices in JavaScript

ClosuresCombines 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

Page 29: Workshop 1: Good practices in JavaScript

Closuresvar 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';

Page 30: Workshop 1: Good practices in JavaScript

Closuresvar fns = [];for (var i=0; i<4; i++) {

fns.push(function() {console.log(i);

});}

fns[0](); // 4fns[1](); // 4fns[2](); // 4fns[3](); // 4

var fns = [];for (var i=0; i<4; i++) { fns.push( (function(a) {

return function() { console.log(a);};

})(i) );}fns[0](); // 0fns[1](); // 1fns[2](); // 2fns[3](); // 3

Page 31: Workshop 1: Good practices in JavaScript

Constructor functionfunction 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 Santaanimal.setName('New Santa');animal.getName();// My name is New Santa

Page 32: Workshop 1: Good practices in JavaScript

Prototype chainvar 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

Page 33: Workshop 1: Good practices in JavaScript

Prototype chainfunction 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

Page 34: Workshop 1: Good practices in JavaScript

Inheritancefunction 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 Clawscat.scratch(); // I love to scratch!

Page 35: Workshop 1: Good practices in JavaScript

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-scop

e-hoisting/● http://davidshariff.com/blog/what-is-the-execution-context-in-j

avascript/● http://davidshariff.com/blog/javascript-scope-chain-and-closure

s/● http://davidshariff.com/blog/javascript-this-keyword/

Page 36: Workshop 1: Good practices in JavaScript

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

Page 37: Workshop 1: Good practices in JavaScript

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

Page 38: Workshop 1: Good practices in JavaScript

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

Page 39: Workshop 1: Good practices in JavaScript

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>

Page 40: Workshop 1: Good practices in JavaScript

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>

Page 41: Workshop 1: Good practices in JavaScript

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>

Page 42: Workshop 1: Good practices in JavaScript

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>

Page 43: Workshop 1: Good practices in JavaScript

More information in...● https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memo

ry_Management● http://www.ibm.com/developerworks/web/library/wa-memleak/● https://msdn.microsoft.com/en-us/magazine/ff728624.aspx

Page 44: Workshop 1: Good practices in JavaScript

Thanks for your attention!Leave your questions on the comments section

Page 45: Workshop 1: Good practices in JavaScript

Recommended