Documents‎ > ‎JavaScript & Client‎ > ‎

JavaScript For Java Programmers V1

By    Abdul Habra
 Version    1.0
 Date    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

Comments