Tamas Rev,
April, 2015
Contact: tamas.rev@gmail.com
Blog: http://tamasrev.wordpress.com/
Twitter: https://twitter.com/tamasrev
Github: https://github.com/rev-tomi/
Surviving javascript
What’s wrong with javascript?
What’s wrong with javascript?
• Wrong
– Scope
– Implicit globals
– Equality
– …
Scopes
demo.scopes = function() {
var a = 0;
for (var i = 0; i < 10; i++) {
var j = i;
a += i;
}
this.appendText('i, after loop: ' + i + '<br>'); // i: 10
this.appendText('j, after loop: ' + j + '<br>'); // j: 9
};
demo.scopes();
Implicit Globals
demo.globals = function() {
var a = 0;
for (i = 0; i < 10; i++) { // oops: no var
a += i;
}
};
demo.globals();
demo.appendText('i: ' + i + '<br>'); // 10
Equality 1
The confusing ones:
"'' == '0'" => false
"0 == ''" => true
"0 == '0'" => true
"false == 'false'" => false
"false == '0'" => true
"false == undefined" => false
"false == null" => false
"null == 'undefined'" => false
What’s wrong with javascript?
• Controversial
– Dynamic typing
– Prototype-based inheritance
Overcoming issues
• Overcoming scope issues
– Using var
– Immediately invoked functions
• Overcoming equality issues
– Using ===
• Overcoming unknown issues
– Using static analyzers
Dealing with scope issues
var demo = function() {
var // var definitions below:
// accessible only from the actual function
sandbox = document.getElementById("sandbox"),
appendText = function(txt) {
sandbox.innerHTML = sandbox.innerHTML + txt;
};
return {
'appendText' : appendText
};
}(); // immediately invoked function expression
// effectively: var demo = { 'appendText' : appendText };
Immediately invoked functions
// how it works
var demo = function () {
…
return {...};
} ();// watch out for ();
// expanded:
var demoCreator = function () {
…
return {...};
};
var demo = demoCreator(); // invoking the function later
Equality 2
The clear ones:
"'' === '0'" => false
"0 === ''" => false
"0 === '0'" => false
"false === 'false'" => false
"false === '0'" => false
"false === undefined" => false
"false === null" => false
"null === 'undefined'" => false
Static analyzers: jshint and jslint
• Both installable with npm. Example package.json:
"dependencies" : {
"jshint" : "2.6.x",
"jslint": ">=0.3.4"
}
• jslint: very strict
• jshint: needs configuration
• Comparison: http://www.smashingmagazine.com/2015/02/18/avoid-javascript-mistakes-
with-static-code-analyzer/
Static analyzer: jshint
• jslint: very strict. Example output:
#3 Missing 'use strict' statement.
var a = 0; // Line 2, Pos 3
#4 Expected 'for' at column 5, not column 3.
for (i = 0; i < 10; i++) { // oops: no var // Line 3, Pos 3
#5 'i' was used before it was defined.
for (i = 0; i < 10; i++) { // oops: no var // Line 3, Pos 8
#6 'i' was used before it was defined.
for (i = 0; i < 10; i++) { // oops: no var // Line 3, Pos 15
• Line #3: warns to use “use strict”
• Line #4: warns about styling issues
• Line #5 and #6: warns about actual problems.
Static analyzer: jshint
• This needs lots of configuration. E.g.:
{
"undef": true,
"unused": true,
"predef": [ "demo", "document" ]
}
• "undef": true // warns you about accidentally defining globals
• This so basic that this should be default
• "unused": true // warns you about things that you can delete
• This is useful. This should be default too
• “predef: ”// lets you to configure vars the come someplace else
• This is actually very useful
Unit test frameworks
• Use unit tests! They’ll catch the majority of subtle bugs
• QUnit - written by the junit team.
• You can run it in your browser
• https://qunitjs.com/
• Mocha - written for node.js
• Comes with various flavors, like TDD, BDD
• You can run it from commandline
• https://qunitjs.com/
• Mocking
• Faking is easy: with dynamic typing you can easily creating fakes
• There are tools for spies, like JsMockito
• http://jsmockito.org/
What’s good about javascript?
• Functional
– Demo: js-list-lazy
• Compact syntax, e.g. inline maps
• Property based => easy to extend
– Demo: tapestry js validations
• Metaprogramming
– Demo: 3.times() …
js-list-lazy
• https://github.com/dankogai/js-list-lazy/ is a list comprehension framework written by Dan Kogai
• Fibonacci example from project page:
var fib = {
0:0,
1:1,
n:1,
get:function(n) {
if (n in this) return this[n];
while(this.n < n)
this[++this.n] = this[this.n-1] + this[this.n-2];
return this[n];
}
},
fb = List.Lazy(fib);
fb.get(22); // 17711
fb.take(10) // [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
Tapestry’s modular validator
• Tapestry is a java web framework with lots of magic
• Extending js validations with custom routines is, however, simple javascript.
• You just add a new property to the Tapestry.Validators object:
Tapestry.Validator.letters = function(field, message) {
field.addValidator(function(value) {
if (value != null) {
if (value.match('[A-Za-z]+') != value) {
throw message;
}
}
});
};
• Source of example: http://jumpstart.doublenegative.com.
au/jumpstart/examples/input/contributingvalidators
Metaprogramming
• This is how you can add a method to numbers:
Number.prototype.times = function(func) {
var i;
for (i = 0; i < this; i++) {
func();
}
};
5['times'](function() {
demo.appendText('hello<br>');
});
Metaprogramming: Mixins 1
• A mixin adds function to another object. E.g. this is how you can add a counter:
var addCounterMixin = function(obj) {
var counter = 0; // state of the mixin
obj.increment = function() {
counter++;
}
obj.getCount = function() {
return counter;
}
}
• And this is how you can use it:
var frici = demo.createCat("Frici");
frici.increment();
demo.appendText(frici.getCount());
Metaprogramming: Mixins 2
• This is the famous comparable mixin:
var addComparableMixin = function(obj) {
obj.smaller = function(other) {
return obj.compareTo(other) === -1; // depending on compareTo
};
obj.greater = function(other) {
return obj.compareTo(other) === 1; // depending on compareTo
};
// ... more operators
}
Further learning
• Douglas Crockford: Javascript, the good parts
Wrapping up
• Easy syntax
• Easy pitfalls
• Static analyzers
• Unit tests
• Raw access to pure magic
• Source of the examples:
https://github.com/rev-tomi/survive-javascript
FAQ
• Can you write mocks with QUnit?
• I don’t think so
• However, you can use JsMockito
• What IDE do you use?
• For java I use eclipse. For js I use editors
like notepad++
• Can you integrate jslint / jshint to eclipse?
• Yes, there are plugins for that
• No, I haven’t tried to do it

Surviving javascript.pptx

  • 1.
    Tamas Rev, April, 2015 Contact:tamas.rev@gmail.com Blog: http://tamasrev.wordpress.com/ Twitter: https://twitter.com/tamasrev Github: https://github.com/rev-tomi/
  • 2.
  • 3.
  • 4.
    What’s wrong withjavascript? • Wrong – Scope – Implicit globals – Equality – …
  • 5.
    Scopes demo.scopes = function(){ var a = 0; for (var i = 0; i < 10; i++) { var j = i; a += i; } this.appendText('i, after loop: ' + i + '<br>'); // i: 10 this.appendText('j, after loop: ' + j + '<br>'); // j: 9 }; demo.scopes();
  • 6.
    Implicit Globals demo.globals =function() { var a = 0; for (i = 0; i < 10; i++) { // oops: no var a += i; } }; demo.globals(); demo.appendText('i: ' + i + '<br>'); // 10
  • 7.
    Equality 1 The confusingones: "'' == '0'" => false "0 == ''" => true "0 == '0'" => true "false == 'false'" => false "false == '0'" => true "false == undefined" => false "false == null" => false "null == 'undefined'" => false
  • 8.
    What’s wrong withjavascript? • Controversial – Dynamic typing – Prototype-based inheritance
  • 9.
    Overcoming issues • Overcomingscope issues – Using var – Immediately invoked functions • Overcoming equality issues – Using === • Overcoming unknown issues – Using static analyzers
  • 10.
    Dealing with scopeissues var demo = function() { var // var definitions below: // accessible only from the actual function sandbox = document.getElementById("sandbox"), appendText = function(txt) { sandbox.innerHTML = sandbox.innerHTML + txt; }; return { 'appendText' : appendText }; }(); // immediately invoked function expression // effectively: var demo = { 'appendText' : appendText };
  • 11.
    Immediately invoked functions //how it works var demo = function () { … return {...}; } ();// watch out for (); // expanded: var demoCreator = function () { … return {...}; }; var demo = demoCreator(); // invoking the function later
  • 12.
    Equality 2 The clearones: "'' === '0'" => false "0 === ''" => false "0 === '0'" => false "false === 'false'" => false "false === '0'" => false "false === undefined" => false "false === null" => false "null === 'undefined'" => false
  • 13.
    Static analyzers: jshintand jslint • Both installable with npm. Example package.json: "dependencies" : { "jshint" : "2.6.x", "jslint": ">=0.3.4" } • jslint: very strict • jshint: needs configuration • Comparison: http://www.smashingmagazine.com/2015/02/18/avoid-javascript-mistakes- with-static-code-analyzer/
  • 14.
    Static analyzer: jshint •jslint: very strict. Example output: #3 Missing 'use strict' statement. var a = 0; // Line 2, Pos 3 #4 Expected 'for' at column 5, not column 3. for (i = 0; i < 10; i++) { // oops: no var // Line 3, Pos 3 #5 'i' was used before it was defined. for (i = 0; i < 10; i++) { // oops: no var // Line 3, Pos 8 #6 'i' was used before it was defined. for (i = 0; i < 10; i++) { // oops: no var // Line 3, Pos 15 • Line #3: warns to use “use strict” • Line #4: warns about styling issues • Line #5 and #6: warns about actual problems.
  • 15.
    Static analyzer: jshint •This needs lots of configuration. E.g.: { "undef": true, "unused": true, "predef": [ "demo", "document" ] } • "undef": true // warns you about accidentally defining globals • This so basic that this should be default • "unused": true // warns you about things that you can delete • This is useful. This should be default too • “predef: ”// lets you to configure vars the come someplace else • This is actually very useful
  • 16.
    Unit test frameworks •Use unit tests! They’ll catch the majority of subtle bugs • QUnit - written by the junit team. • You can run it in your browser • https://qunitjs.com/ • Mocha - written for node.js • Comes with various flavors, like TDD, BDD • You can run it from commandline • https://qunitjs.com/ • Mocking • Faking is easy: with dynamic typing you can easily creating fakes • There are tools for spies, like JsMockito • http://jsmockito.org/
  • 17.
    What’s good aboutjavascript? • Functional – Demo: js-list-lazy • Compact syntax, e.g. inline maps • Property based => easy to extend – Demo: tapestry js validations • Metaprogramming – Demo: 3.times() …
  • 18.
    js-list-lazy • https://github.com/dankogai/js-list-lazy/ isa list comprehension framework written by Dan Kogai • Fibonacci example from project page: var fib = { 0:0, 1:1, n:1, get:function(n) { if (n in this) return this[n]; while(this.n < n) this[++this.n] = this[this.n-1] + this[this.n-2]; return this[n]; } }, fb = List.Lazy(fib); fb.get(22); // 17711 fb.take(10) // [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
  • 19.
    Tapestry’s modular validator •Tapestry is a java web framework with lots of magic • Extending js validations with custom routines is, however, simple javascript. • You just add a new property to the Tapestry.Validators object: Tapestry.Validator.letters = function(field, message) { field.addValidator(function(value) { if (value != null) { if (value.match('[A-Za-z]+') != value) { throw message; } } }); }; • Source of example: http://jumpstart.doublenegative.com. au/jumpstart/examples/input/contributingvalidators
  • 20.
    Metaprogramming • This ishow you can add a method to numbers: Number.prototype.times = function(func) { var i; for (i = 0; i < this; i++) { func(); } }; 5['times'](function() { demo.appendText('hello<br>'); });
  • 21.
    Metaprogramming: Mixins 1 •A mixin adds function to another object. E.g. this is how you can add a counter: var addCounterMixin = function(obj) { var counter = 0; // state of the mixin obj.increment = function() { counter++; } obj.getCount = function() { return counter; } } • And this is how you can use it: var frici = demo.createCat("Frici"); frici.increment(); demo.appendText(frici.getCount());
  • 22.
    Metaprogramming: Mixins 2 •This is the famous comparable mixin: var addComparableMixin = function(obj) { obj.smaller = function(other) { return obj.compareTo(other) === -1; // depending on compareTo }; obj.greater = function(other) { return obj.compareTo(other) === 1; // depending on compareTo }; // ... more operators }
  • 23.
    Further learning • DouglasCrockford: Javascript, the good parts
  • 24.
    Wrapping up • Easysyntax • Easy pitfalls • Static analyzers • Unit tests • Raw access to pure magic • Source of the examples: https://github.com/rev-tomi/survive-javascript
  • 25.
    FAQ • Can youwrite mocks with QUnit? • I don’t think so • However, you can use JsMockito • What IDE do you use? • For java I use eclipse. For js I use editors like notepad++ • Can you integrate jslint / jshint to eclipse? • Yes, there are plugins for that • No, I haven’t tried to do it