JavaScript For Java Programmers V1

By

Version

Date

Abdul Habra

1.0

2011.11.09

These are the code sample used in the presentation.

// References:

// JavaScript: The Good Parts by Douglas Crockford, 2008

// Eloquent JavaScript by Marijn Haverbeke, 2011

// JavaScript Enlightenment by Cody Lindley, 2011

// http://javascript.crockford.com/code.html

//// EXPECTATIONS

// javasript for java programmers

// Mantra: javascript has no classes

//// to var or not to var

// run this with jasmine

var x=1;

y=2;

console.log(window.x, window.y, 'x' in window, 'y' in window);

///////// falsy values

0, NaN, '', "", false, null, undefined

//// == or ===

console.log(0 == false, 0===false);

console.log(0 == "", 0==="");

console.log(7 == "7", 7==="7");

console.log("8" == "8", "8"==="8");

////////// null and undefined are types

var a= null;

var b= undefined;

console.log(typeof a, typeof b);

console.log(c);

///////// creating an object

var obj1= {};

var obj2= new Object();

console.log(typeof obj1);

console.log(typeof obj2);

///// defining properties on objects

var obj= {k1:1, k2:2};

obj.prop1= 'hello';

obj['my prop2']= new Date();

console.log(obj);

delete obj.k2;

console.log(obj);

console.log('k2' in obj);

////// strings

var s1= new String('hello');

var s2= 'hello';

console.log(s1, s2);

console.log(typeof s1, typeof s2); // object string

////// adding property to an instance

var s1= new String("hello");

s1.prop1=42;

console.log(s1, s1.prop1); // notice how we can add property to any object

var s2= 'hello';

s2.prop2=43;

console.log(s2, s2.prop2);

//////// adding method to an existing prototype (class)

String.prototype.substringAfter = function(start) {

var i= this.indexOf(start);

if (i<0) return '';

return this.substr(i+start.length);

}

console.log('abcde'.substringAfter('c'));

console.log('substringAfter' in String.prototype);

delete String.prototype.substringAfter;

console.log('substringAfter' in String.prototype);

//////// using for in

var ar= [10, 20, 30];

for (var k in ar) {

console.log(k, ar[k]); // notice how k is the key/index

}

var person= {fname:'abdul', lname:'habra', pay:100};

for (var k in person) {

console.log(k, person[k]);

}

// so far for in is ok, but consider this

Array.prototype.prop1 = 'some libraries do this';

var ar2= [10, 20, 30];

for (var k in ar2) {

console.log(k, ar2[k]); // notice how we have 4 elements now

}

// solve it like this

for (var k in ar2) {

if (ar2.hasOwnProperty(k)) {

console.log(k, ar2[k]);

}

}

// better yet

_.each(ar2, function(value) {

console.log(value);

});

////////// declaring functions: 4 ways

function statment(x,y) {return x+y;};

var expression= function(x,y) {return x+y;};

var namedExpression= function f(x,y) { return x+y;}

var functionConstructor= new Function('x', 'y', 'return x+y;');

console.log(statment(1,3));

console.log(expression(1,3));

console.log(namedExpression(1,3));

console.log(functionConstructor(1,3));

///////// reflecting on function parameters

function f1() {

for (var k in arguments) {

console.log(k, arguments[k]);

}

}

f1('a', 'b', 11)

////////////// Anonymous functions

// suppose I have an object with method setCallback,

// which takes a function

// regular function:

function f1(x) { return x*3;}

obj.setCallback(f1);

// or Anonymous functions

obj.setCallback( function(x) { x*3}; )

// self invoking function

var f = function(a,b) {console.log(a+b)} (1,2);

// self invoking Anonymous functions

(function(msg) { console.log(msg);} ) ('hello');

(function(msg) { console.log(msg);} ('hello'));

//////// order of functions

// run this with jasmine

f1();

f2();

function f1() {

console.log('in f1');

}

var f2= function() {

console.log('in f2');

}

//// exceptions

function playWithExceptions() {

try {

console.log('in try');

throw 'wow';

} catch(error) {

console.log('in catch:', error.message);

}

console.log('after catch');

}

///// simulating a class declaration: Constructor function

// Good for singletons

function PolitePersonSingleton(name, age, sex) {

this.getAge = function() {

return sex==='f'? age/2 : age;

}

};

var john = new PolitePersonSingleton('john', 40, 'm');

var jane = new PolitePersonSingleton('jane', 40, 'f');

// if you forget "new", then, "this" is bound to global object

console.log('john age ', john.getAge());

console.log('jane age ', jane.getAge());

///// private/public methods

function PolitePersonSingleton(name, age, sex) {

this.getAge = function() {

return sex==='f'? age/2 : age;

};

function calculateIQ() {

return Math.random() * 200;

};

var privateVar=1;

this.publicVar=2;

};

var john= new PolitePersonSingleton('john', 40, 'm');

john.calculateIQ();

console.log(john.privateVar);

console.log(john.publicVar);

//// Simulating class with many instances

function HonestPerson(name, age, sex) {

function getAge() {

return sex==='f'? age*0.8 : age;

};

function calculateIQ() {

return Math.random() * 200;

};

var privateVar=1;

var publicVar=2;

return {

getAge: getAge,

publicVar: publicVar

};

};

var jane= HonestPerson('jane', 40, 'f'); // No new

var john= HonestPerson('john', 40, 'm');

console.log('john age ', john.getAge());

console.log('jane age ', jane.getAge());

//john.calculateIQ();

console.log(john.privateVar);

console.log(john.publicVar);

//// simulating class with many instances: add properties

function HonestPerson(name, age, sex) {

var that= {}; // properties container. do not use this or self

var privateVar=1;

var publicVar=2;

function getAge() {

return sex==='f'? age*0.8 : age;

};

function calculateIQ() {

return Math.random() * 200;

};

function setJob(job) { that.job= job; }

function getJob() { return that.job; }

function toString() {

return 'name=' + name + ', age=' + age +

', sex=' + sex + ', job=' + that.job;

};

return {

getAge: getAge,

publicVar: publicVar,

setJob: setJob,

getJob: getJob,

toString: toString

};

};

var jane= HonestPerson('jane', 40, 'f');

var john= HonestPerson('john', 40, 'm');

jane.setJob('doctor');

john.setJob('nurse');

console.log('john job ', john.getJob());

console.log('jane job ', jane.getJob());

console.log(john.toString());

console.log(jane.toString());

///// regular expressions

var regex1= /a.*/;

console.log(regex1.test('ab'));

console.log(regex1.test('bb'));

//////// UNEXPECTED BEHAVIOR (from java programmers perspective)

///// semicolon insertion

function f1() {

return

true;

}

console.log(f1());

// be extra careful specially when you return objects like { ... }

///// parseInt

console.log(parseInt("06"));

console.log(parseInt("07"));

console.log(parseInt("08"));

console.log(parseInt("08", 10));

///// arrays boundries

var ar= ['a', 'b', 'c'];

console.log(ar);

ar[0]= 'A';

ar[1]= 'B';

ar[2]= 'C';

ar[30]= 'D'; // oops typo. "array out of bound exception"?

console.log(ar);

///// parsing text, be careful with keys

var text= 'praise thine Lord and Constructor';

var words= text.toLowerCase().split(' ');

var count= {};

for (var i=0, n=words.length; i<n; i++) {

var word= words[i];

if (count[word]) {

count[word] = count[word] + 1;

} else {

count[word]= 1;

}

}

//console.log(count); // what do you expect?

//////////// What's next

// Consider underscore.js

// consider backbone.js