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