Friday 25 November 2016

Javascript: every, some, arrow function

Array.every() returns true when all the items meet certain condition

var nums = [5,7,10,17,20];
var nums2 = [11,17,20,23];

var allBig = nums.every(function(element){
    return element > 10;
});

console.log(allBig); //false

//ES6 arrow function
allBig = nums.every(element => element > 10);

console.log(allBig); //false

allBig = nums2.every(function(element){
    return element > 10;
});

console.log(allBig); //true

//ES6 arrow function
allBig = nums2.every(element => element > 10);

console.log(allBig); //true

Array.some() returns true when any item meets certain condition.
var nums = [5,7,10,17,20];
var nums2 = [11,17,20,23];

var allBig = nums.some(function(element){
    return element > 10;
});

console.log(allBig); //true

//ES6 arrow function
allBig = nums.some(element => element > 10);

console.log(allBig); //true

allBig = nums2.some(function(element){
    return element > 30;
});

console.log(allBig); //false

//ES6 arrow function
allBig = nums2.some(element => element > 30);

console.log(allBig); //false

Thursday 24 November 2016

Effective Java Item 35. Write own annotation and reflection

 //Almost always RUNTIME  
 @Retention(RetentionPolicy.RUNTIME)  
 @Target({ElementType.TYPE, ElementType.METHOD})  
 @interface MyTest {}  
 class Sample{  
   @MyTest  
   public static void m1(){}  
 }  
 public class MyAnnotation{  
   public static void main(String[] args){  
     Class testClass = Sample.class;  
     //Get all methods including private, protected  
     //as opposed to testClass.getMethods() only returning public methods  
     for (Method m : testClass.getDeclaredMethods()){  
       if (m.isAnnotationPresent(MyTest.class)){  
         try{  
           m.invoke(null); //Call static method  
         } catch (InvocationTargetException e) {  
           e.printStackTrace();  
         } catch (Exception e) {  
           e.printStackTrace();  
         }  
       }  
     }  
   }  
 }  

Javascript: check undefined/null

If you are sure the variable has been declared (i.e var a;), simply use
if (a != null){
    ...
}
If a can be undeclared, then use


if (typeof a != 'undefined' && a != null){
    ...
}

Javascript: softbind

Excerpted from You Don't Know JS: this & Object Prototypes

I couldn't fully understand the code below.
  
if (!Function.prototype.softBind) {
    Function.prototype.softBind = function(obj) {
        var fn = this,
            curried = [].slice.call( arguments, 1 ),
            bound = function bound() {
                return fn.apply(
                    (!this ||
                        (typeof window !== "undefined" &&
                            this === window) ||
                        (typeof global !== "undefined" &&
                            this === global)
                    ) ? obj : this,
                    curried.concat.apply( curried, arguments )
                );
            };
        bound.prototype = Object.create( fn.prototype );
        return bound;
    };
}

function foo() {
   console.log("name: " + this.name);
}

var obj = { name: "obj" },
    obj2 = { name: "obj2" },
    obj3 = { name: "obj3" };

var fooOBJ = foo.softBind( obj );

fooOBJ(); // name: obj

obj2.foo = foo.softBind(obj);
obj2.foo(); // name: obj2   <---- look!!!

fooOBJ.call( obj3 ); // name: obj3   <---- look!

setTimeout( obj2.foo, 10 ); // name: obj   <---- falls back to soft-binding
  1. What does [].slice.call(...) do? 
  2. Are the two 'this' referring to the same thing? 
  3. What does bound.prototype = Object.create(fn.prototype) do?
Let's go through the code step by step by inserting some console output code. And for the sake of demonstrating the purpose of curried, I also rewrote the foo() function.
if (!Function.prototype.softBind) {
    Function.prototype.softBind = function(obj) {
        var fn = this;
        console.log("Outer this = "+ fn);
        var curried = [].slice.call( arguments, 1 );
        console.log("Outer curry = "+curried);
        var bound = function bound() {
            console.log("Inner this = " + this);
            console.log("Inner curry = "+curried.concat.apply( curried, arguments ));
            return fn.apply(
                (!this ||
                    (typeof window !== "undefined" &&
                        this === window) ||
                    (typeof global !== "undefined" &&
                         this === global)
                ) ? obj : this,
                curried.concat.apply( curried, arguments )
            );
        };
        bound.prototype = Object.create( fn.prototype );
        console.log("return bound");
        return bound;
    };
}

function foo(a1, a2) {
   console.log(a1 + ' ' +a2 + " name: " + this.name);
}

var obj = { name: "obj" },
    obj2 = { name: "obj2" },
    obj3 = { name: "obj3" };

var fooOBJ = foo.softBind( obj, 'A1');
fooOBJ('A2'); // name: obj

//obj2.foo = foo.softBind(obj, 'A1');
//obj2.foo('A2'); // name: obj2   <---- look!!!

//fooOBJ.call( obj3 ); // name: obj3   <---- look!
Here is the output.
Outer this = function foo(a1, a2) {
   console.log(a1 + ' ' +a2 + " name: " + this.name);
}
Outer curry = A
return bound
Inner this = [object Object]
Inner curry = A,A2
A A2 name: obj2

[].slice.call(arguments, 1)
is semantically equal to
arguments.slice(1)
except the latter is syntactically incorrect because the variable arguments is not a real array. It's an 'array-like' object.

The outer this refers to the foo function while the inner this refers to the window (global) variable. It's worth noting that by the time foo.softBind(obj) completes execution, the bound() function hasn't been invoked. It's only invoked when the line fooOBJ('A2') is executed.

bound.prototype = Object.create( fn.prototype );
copies all the properties of foo to bound, essentially ensuring that after softbind the function foo doesn't lose any properties.

Wednesday 23 November 2016

Javascript: dabble in 'new'

The code snippet below demonstates the difference between invoking a function with and without new.
function foo(a) {
    this.a = a;
}

var bar = new foo( 2 );
var bar2 = foo( 2 );

console.log( bar); // foo {a: 2}
console.log( bar.a); // 2
console.log( bar2); // undefined 
console.log( bar2.a); // TypeError
Why bar2 is undefined? Because there is no return statement in foo(). What if there is?
function foo(a) {
    this.a = a;
    return this;
}

var bar = new foo( 2 );
var bar2 = foo( 2 );

console.log( bar); // foo {a: 2}
console.log( bar.a); // 2
console.log( bar2); // Window {top: Window, location: Location, document: document, window: Window, external: Object…}
console.log( bar2.a); // 2
Why bar2.a = 2 while bar2 itself is the Window object? Because this refers to the Window object and this.a essentially creates an 'a' variable in global scope (Window object). Now what if returning something other than this?
function foo(a) {
    this.a = a;
    return 3;
}

var bar = new foo( 2 );
var bar2 = foo( 2 );

console.log( bar); // foo {a: 2}
console.log( bar.a); // 2
console.log( bar2); // 3
console.log( bar2.a); // undefined
Oh, it turns out that having a 'new' precede a function ignores the return statement all together. Although the author of stresses that 'new' in Javascript has nothing to do with the constructor concept in class-oriented languages, I, with a Java background, am still inclined to interpret it as:
class foo{
    var a;
 
    public foo(a){
        this.a = a;
    }
}

var bar = new foo(2);

Tuesday 22 November 2016

Javascript: 'this' and call

In this post, my assertion that

impl.apply(impl, deps) = impl.apply(null, deps);

just shows how naive I was due to the lack of understanding of 'this' mechanism.

From You Don't Know JS: this & Object Prototypes

function foo(num) {
    console.log( "foo: " + num );

    // keep track of how many times `foo` is called
    // Note: `this` IS actually `foo` now, based on
    // how `foo` is called (see below)
    this.count++;
}

foo.count = 0;

var i;

for (i=0; i<10; i++) {
    if (i > 5) {
        // using `call(..)`, we ensure the `this`
        // points at the function object (`foo`) itself
        foo.call( foo, i );
    }
}
// foo: 6
// foo: 7
// foo: 8
// foo: 9

// how many times was `foo` called?
console.log( foo.count ); // 4 
The first parameter foo essentially makes 'this' point to the foo object.
Now replace the line with

foo.call( null, i );

It prints out '0' because this refers to window object now.

I am tempted to boldly make this assertion that the following two pairs of method invocation can always be used interchangeably.

foo.call( foo, i ) = foo.bind(foo)(i)
foo.call( null, i) = foo(i)  

Let's see when I can be proved wrong.


Javascript: dabble in 'this'

It is probably going to take me a while to fully grasp the 'this' concept in Javascript. Today I just dabble in the topic and present my shallow understandings.

It still comes from You Dont Know Js Scope and Closure, Appendix C: Lexical this.

var obj = {
    id: "awesome",
    cool: function coolFn() {
        console.log( this.id );
    }
};

var id = "not awesome";

obj.cool(); // awesome

setTimeout( obj.cool, 100 ); // not awesome

It looks like when invoked from setTimeout(), this refers to the window object. Then the author introduced various solutions, including self, bind(), and a new feature of ES6: arrow function. These are all cool stuff. But how to address the original problem -- that is, to get setTimeout() function to print 'awesome' as well?

The simplest solution is replace this with obj

console.log( obj.id );

Then I attempt to use bind().

cool2: function coolFn2() {
    console.log( this.id );
}.bind(obj)
It doesn't work because obj cannot be referenced within itself, well, unless it is referenced within a function. Therefore the 2nd attempt.

cool3: function coolFn3() {
    (function(){
        console.log(this.id); 
    }.bind(obj))();
} 
Hey it works. I wouldn't have come up with this solution if I hadn't read the previous chapters of 'You Dont Know Js'. So once again, kudos to the author.

Javascript: apply

In You Dont Know JS Chapter 5: Scope Closure, there is following code snippet to illustrate the power of module pattern.

var MyModules = (function Manager() {
    var modules = {};

    function define(name, deps, impl) {
        for (var i=0; i<deps.length; i++) {
            deps[i] = modules[deps[i]];
        }
        modules[name] = impl.apply(impl, deps);
        console.log("module "+modules[name]);
    }

    function get(name) {
        return modules[name];
    }

    return {
        define: define,
        get: get
    };
})();

MyModules.define( "bar", [], function(){
    function hello(who) {
        return "Let me introduce: " + who;
    }

    return {
        hello: hello
    };
} );

MyModules.define( "foo", ["bar"], function(bar){
    var hungry = "hippo";

    function awesome() {
        console.log( bar.hello( hungry ).toUpperCase() );
    }

    return {
        awesome: awesome
    };
} );

var bar = MyModules.get( "bar" );
var foo = MyModules.get( "foo" );

console.log(bar.hello( "hippo" )); // Let me introduce: hippo

foo.awesome(); // LET ME INTRODUCE: HIPPO

What does this line do?
modules[name] = impl.apply(impl, deps);

It is another way of invoking a function, sort of like Java reflection. And we get to pass an array variable in the second argument to replace a list of parameters. What is the first argument for?

According  to https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply

fun.apply(thisArg, [argsArray])

Parameters

thisArg
The value of this provided for the call to fun. Note that this may not be the actual value seen by the method: if the method is a function in non-strict mode code, null and undefined will be replaced with the global object, and primitive values will be boxed.
I don't quite understand this definition. As far as I am concerned,

fun.apply(thisArg, [argsArray]) = thisArg.fun(arg1, arg2....)

In this case, I also don't understand why the first parameter is 'impl'. But I have proved it can be replaced with 'null'.

The next question is why the function needs to be called in such a unconventional way. Could it be called normally?

If we put

modules[name] = impl(deps);

bar.hello() executes OK, but foo.awsome() throws TypeError: bar.hello is not a function.

Then try

modules[name] = impl(deps[0]);

It does work. But obviously it's not a universal solution. Hence the use of apply().

Thursday 17 November 2016

Javascript: Closure + Loop

What does this program print out?
for (var i=1; i<=5; i++) {
    setTimeout( function timer(){
        console.log( i );
    }, i*1000 );
}
At first glance, it seems to print 1,2,3,4,5, at 1 second interval. But in fact, it prints 6,6,6,6,6 at 1 second interval. What is going on?

At second glance, it does make sense. The timer() function is invoked after the waiting period (i*1000). By the time it starts to execute, the for loop has long finished. And at this point of time, i = 6.

So how to fix it? 

By wrapping the setTimeout() with a function makes the variable j local to the enclosing function.

for (var i=1; i<=5; i++) {
    (function(){
        var j = i;
 setTimeout( function timer(){
     console.log(j);
        }, i*1000 );
    })();
}
A neater variation.
for (var i=1; i<=5; i++) {
    (function(j){
 setTimeout( function timer(){
     console.log(j);
        }, i*1000 );
    })(i);
}
Even better is replace var with let (ES6 feature)
for (let i=1; i<=5; i++) {
    setTimeout( function timer(){
 console.log(i);
    }, i*1000 );
}
This is most surprising. It turns out let not only restrain the variable within the for loop but also each iteration!

Wednesday 16 November 2016

Javascript: What is the difference between function foo(){...} and var foo = function(){...}

()This has been puzzling me for a long time.
function bar(){
    console.log("bar");
}

var foo = function (){
    console.log("foo");
}

bar();
foo();

What's the difference between these two formats?

I always use the first format to declare a function and deem the second format as an advanced, fancy one.

Now I learnt that the 'fancy' format is actually the less preferred way to declare the function because the function must be called after its declaration while in first format the function can be called anywhere.


bar(); //Print 'bar'
foo(); //TypeError

function bar(){
    console.log("bar");
}

var foo = function (){
    console.log("foo");
}

It turns out Javascript compiler moves all the declaration (e.g. var a) to the top and leaves the assignment (a = 2) where it is.  (By the way, I wasn't aware Javascript has a compiler until today)

So the above code is interpreted by the compiler as

function bar(){
    console.log("bar");
}

var foo;

bar(); //Print 'bar'
foo(); //TypeError

foo = function (){
    console.log("foo");
}

function bar() is moved to top as a whole but function foo is separated into var foo and foo = ...

Another point worth mentioning is that function declaration (in first format) overrides the same function name.


function bar(){
    console.log("bar");
}

bar(); //Print 'foo'

function bar(){
    console.log("foo");
}




Tuesday 15 November 2016

Javascript: function expression

I often came across this pattern in javascrip code and never understood the advantage of it.

(function(window, document, undefined){
    window.MyObject = {
        methodA: function() { ... },
        methodB: function() { ... }
    };
})(window, document)

After reading You don't know JS (a great book), I finally came to understand this pattern. Here is a summary of my understanding.

This is how we normally define and call a js function:

var a = 2;

function foo(){
    var a = 3;
    console.log("inner a =" + a ); // 3
}; 

console.log("outer a = " + a ); //2

foo();

It is not ideal because we have to explictly call foo() to execute the function. If we just wish to call this method once and done, we have wasted one line of code.

Another issue is that it "pollutes the enclosing scope (quote the book)". I am personally OK with that. It's just one less variable name available for using.

Javascript has a solution to both problems:

var a = 2;

(function foo(){
    var a = 3;
    console.log("inner a =" + a ); // 3
})(); 

console.log("outer a = " + a ); //2

foo(); //ReferenceError

By wrapping the whole function with (), appending another pair of (), we are able to execute the function directly.

More significantly, now the variable foo is not accessible in global scope (Attemping to access it throws a refrenceError). In fact, foo is only accessible within the function scope.

Since it's unlikely to access foo variable within the function scope, anonymous function is preferred here.

(function (){
    var a = 3;
    console.log("inner a =" + a ); // 3
})();

A variation of this form is moving the second pair of () inside the first pair ()

(function (){
    var a = 3;
    console.log("inner a =" + a ); // 3
}());

These two forms are identical in functionality.

Parameter can be passed to the function. Now it looks more and more like the most common seen format in the js library code.


var a = 3;

(function (window){
    var a = 2;
    console.log( "a = "+a);
    console.log( "global a = "+window.a);    
})(window);

The book says another usage of the pattern is to address the issue of the value of undefined identifier being overwritten.

var undefined = true; // setting a land-mine for other code! avoid!

(function (){
    var a;
    if (a === undefined) {
        console.log( "a is undefined"); //still undefined
    }else{
        console.log( "a is defined" );
    }
})();

After experimenting, it turns out you can't overwrite the value of undefined in global scope -- You can only overwrite it within a function sceop. So in order to demonstrate the usage, I wrap the code with a function.

function foo(){

    var undefined = true; // setting a land-mine for other code! avoid!

    (function (){
        var a;
        if (a === undefined) {
            console.log( "a is undefined");
        }else{
            console.log( "a is defined" ); //becomes defined
        }
    })();
}

By defining an undefined paramater and not passing any value for that argument, undefined is guaranteed to be undefined.

function foo(){

    var undefined = true; // setting a land-mine for other code! avoid!

    (function (undefined){
        var a;
        if (a === undefined) {
            console.log( "a is undefined"); //Undefined, yeah!
        }else{
            console.log( "a is defined" );
        }
    })();
}

Sunday 13 November 2016

Javascript: Calculate Inbreeding Coefficient

A little background:

http://cal.vet.upenn.edu/projects/genetic/inbreed/coeff/page1.htm
http://cal.vet.upenn.edu/projects/genetic/inbreed/coeff/page2.htm






Fx = the coefficient of inbreeding of individual x
n = number of generations from the sire (father) of x back to some ancestor common to the sire and dam

n' = number of generations from the dam (mother) of x back to some ancestor common to the sire and dam

Fa = coefficient of inbreeding of the common ancestor when that animal is itself inbred

∑ = summation of the separate contributions of each common ancestor (the summation here refers to all possible pathways by which an allele could be passed from the common ancestor to both parents)














Let's start with an example.

We have two common ancestors here: 1 and 2

First calculate the contribution from common ancestor 1.

n = the number of generations from the sire (in this case 3) to the common ancestor 1, that is 1
n' = the number of generations from the sire (in this case 3) to the common ancestor 1, that is also 1

(1/2)^(1+1+1)*(1+0) = 1/8.

Why Fa = 0? Because the inbreeding coefficient of common ancestor 1 is 0.

Contribution from common ancestor 2 is apparently also 1/8 due to symmetry.

Thus, the inbreeding coefficient of x Fx = 1/8 + 1/8 = 1/4 = 0.25

I decide to use Javascript to implement this equation. 

A crucial task is to find all the common ancestors. In this case it is easy to spot 1 and 2. Things get trickier when father mates daughter. We may end up with some common ancestors which should be excluded from the calculation. Check this complex scenario.












In this case, by definition, F, C, E, D, G are all common ancestors of A and B, since B is A's daughter. In fact, F, C, E, D have no contribution towards inbreeding coefficient. However, G does make contribution because it can reach B through another path that doesn't contain A (GHB).

We break the task down into finding the ancestors of father and mother respectively, then find the common ones.

1. Not ony do we need to know the ancestor, but also we need to know the path. (In my program, I call it 'chain')

So for father A, we have 6 ancestors (including himself) but 7 paths

A
A C
A C F
A C E
A D
A D E
A D G

For mother B, we have 9 ancestors (everyone except x) but 11 paths

B
B A
B A C
B A C F
B A C E
B A D
B A D E
B A D G
B H
B H G
B H M

2. Compare each pair of paths between A and B. The last element of the path is a common ancestor candidate. Needless to say, the last element of the pair needs to match one another to start with. Then we check in addtion to the last element, is there any other common element? If there is, we need to ditch this common ancestor (e.g. E in ACE and BACE) too because it doesn't contribute towards inbreeding coefficient as discussed earlier. Finally we identify two common ancestors: A (A, AB) and G (ADG, BHG). The length of two paths combined minus 1 is actually the n+n'+1 part in the equation.

Technical note. For the first time, I try to use a Javascript unit test framework -- QUnit. It has similar syntax to JUnit, and I found it very pleasant to use.

Highlight of new stuff learnt.
  • QUnit
  • Javascript closure/module
  • slice() method - used to copy array and get the last item of the array
Let's quickly check some results

ScenarioInbreeding coefficient
Full siblings 0.25
Father daughter 0.25
Half siblings0.125
First cousins0.0625
3 generation full siblings0.5

Finally the code (https://github.com/sunmingtao/inbreed)

The Person.inbreedingCoefficient.complex test case corresponds to the 2nd complex scenario above.

inbreeding.js
 'use strict';  
  function Person(name, father, mother){  
      var myFather, myMother;  
      doFather(father);  
      doMother(mother);  
      function doFather(father){  
           if (notNull(father)){  
                myFather = father;       
                return;  
           }  
           return myFather;  
      }  
      function doMother(mother){  
           if (notNull(mother)){  
                myMother = mother;            
                return;  
           }  
           return myMother;  
      }  
      function doHasFather(){  
           return doHasParent(myFather);  
      }  
      function doHasMother(){  
           return doHasParent(myMother);  
      }  
      function doHasParent(parent){  
           return notNull(parent);  
      }  
      function doInbreedingCoefficient(){  
           var fatherChains = doFatherChains();  
           logChains(fatherChains, "Father chains of "+name);  
           var motherChains = doMotherChains();  
           logChains(motherChains, "Mother chains of "+name);  
           var result = 0;  
           for (var i=0; i<fatherChains.length; i++){  
                for (var j=0; j<motherChains.length; j++){  
                     var num = numberGenerationToCommonAncestor(fatherChains[i], motherChains[j]);  
                     if (num) { //is a common ancestor  
                          var commonAncestor = fatherChains[i].fathestAncestor();  
                          console.log("Found common ancestor: "+commonAncestor.name+". Num is "+num);  
                          result += Math.pow(0.5, num)*(1+commonAncestor.inbreedingCoefficient());  
                     }  
                }  
           }  
           return result;  
      }  
      function doFatherChains(){  
           return doParentChains(myFather);  
      }  
      function doMotherChains(){  
           return doParentChains(myMother);  
      }  
      function doParentChains(parent){  
           var chains = [];  
           if (doHasParent(parent)){  
                chains.push(Chain([parent])); //parent itself  
                var ancestors = parent.chains(); //All parents' ancestors  
                for (var i = 0; i < ancestors.length; i++){  
                     var chain = ancestors[i];  
                     chain.prepend(parent);  
                     chains.push(chain);  
                }  
           }  
           return chains;  
      }  
      function doChains(){  
           return doFatherChains().concat(doMotherChains());  
      }  
      var publicAPI = {  
           name: name,  
           father: doFather,  
           mother: doMother,  
           hasFather: doHasFather,  
           hasMother: doHasMother,  
           fatherChains: doFatherChains,  
           motherChains: doMotherChains,  
           chains: doChains,  
           inbreedingCoefficient: doInbreedingCoefficient  
      };  
      return publicAPI;  
  }  
  function Chain(persons){  
       var myChain = persons;  
       function getChain(){  
            return myChain;  
       }  
       function doPrepend(person){  
            myChain.unshift(person);  
       }  
       function getLength(){  
            return myChain.length;  
       }  
       function getFathestAncestor(){  
            return myChain.slice(-1)[0];  
       }  
       function doToString(){  
            var result = '';  
            for (var i=0; i<persons.length; i++){  
                 result += persons[i].name + ' ';  
            }  
            return result;  
       }  
       return {  
           chain : getChain,  
           prepend: doPrepend,  
           length: getLength,  
           fathestAncestor: getFathestAncestor,  
           toString: doToString  
       };  
  }  
 //returns the number of nodes to go from start point of chain 1 (item 0) to common ancestor, then to the start point of chain 2  
 //if two pathways to the common ancestor share a portion of same route, return 0. chain 1 = [a, c, f, g], chain 2 = [b, d, f, g].   
 //In this case, f is deemed 'common ancestor', g is not (because fg is shared by both chains)  
 //e.g.1 chain 1 = [a, c, f], chain 2 = [b, f], then traverse acfb, return 4  
 //e.g.2 the start point itself is a common ancestor. chain 1 = [a], chain 2 = [b, a], then traverse ab, return 2  
 //e.g.3 if no common ancestor, return 0. chain 1 = [a, c], chain 2 = [b, d]  
 function numberGenerationToCommonAncestor(chain1, chain2){  
      if (chain1.fathestAncestor() != chain2.fathestAncestor() || hasCloserCommonAncestor(chain1, chain2)){  
           return 0;  
      }  
      return chain1.length() + chain2.length() - 1;  
 }  
 //Check if other closer common ancestor exists apart from the farthest common ancestor  
  function hasCloserCommonAncestor(chain1, chain2){  
       var persons1 = chain1.chain().slice(); //make a copy  
       var persons2 = chain2.chain().slice();  
       persons1.pop(); //chop off the last item  
       persons2.pop();  
       for (var i=0; i<persons1.length; i++){  
            for (var j=0; j<persons2.length; j++){  
                 if (persons1[i] == persons2[j]){  
                      return true;  
                 }  
            }  
       }  
       return false;  
  }  
  function logChains(chains, message){  
      console.log(message);   
      for (var i=0; i<chains.length; i++) {  
           console.log(chains[i].toString());  
      }        
  }  
  function notNull(v){  
       return typeof v !== 'undefined' && v !== null;  
  }  

tests.js
 QUnit.test( "Person.init", function( assert ) {  
      var a = Person('a');  
      assert.equal( a.name, 'a');  
      var b = Person('b');  
      var c = Person('c', a , b);  
      assert.equal(c.mother().name, b.name);  
      var d = Person('d');  
      d.father(a);  
      d.mother(b);  
      assert.equal(d.mother().name, b.name);  
 });  
 QUnit.test( "Person.hasFatherMother", function( assert ) {  
      var a = Person('a');  
      assert.equal( a.hasFather(), false);  
      var b = Person('b');  
      var c = Person('c', a , b);  
      assert.equal( c.hasFather(), true);  
      var d = Person('d');  
      d.father(a);  
      d.mother(b);  
      assert.equal( d.hasMother(), true);  
 });  
 QUnit.test( "Person.chain", function( assert ) {  
      var a = Person('a');  
      assert.equal( a.fatherChains().length, 0);  
      var b = Person('b');  
      var c = Person('c', a , b);  
      assert.equal( c.fatherChains().length, 1);  
      assert.equal( c.fatherChains()[0].chain()[0].name, 'a');  
 });  
 QUnit.test( "Person.longer.chain", function( assert ) {  
      var a = Person('a');  
      var b = Person('b');  
      var c = Person('c', a , b);  
      var d = Person('d');  
      var e = Person('e', c, d);  
      assert.equal( e.fatherChains().length, 3);  
      assert.equal( e.fatherChains()[0].chain().length, 1);   
      assert.equal( e.fatherChains()[0].chain()[0].name, 'c');  
      assert.equal( e.fatherChains()[1].chain().length, 2);  
      assert.equal( e.fatherChains()[1].chain()[0].name, 'c');  
      assert.equal( e.fatherChains()[1].fathestAncestor().name, 'a');  
      assert.equal( e.fatherChains()[2].chain().length, 2);  
      assert.equal( e.fatherChains()[2].chain()[0].name, 'c');  
      assert.equal( e.fatherChains()[2].fathestAncestor().name, 'b');  
 });  
 QUnit.test( "Chain.prepend", function( assert ) {  
      var a = Person('a');  
      var chain = Chain([a]);  
      assert.equal( chain.length(), 1);  
      var b = Person('b');  
      chain.prepend(b);  
      assert.equal( chain.length(), 2);  
      assert.equal( chain.chain()[0].name, 'b');  
 });  
 QUnit.test("numberGenerationToCommonAncestor", function( assert ) {  
      var a = Person('a');  
      var b = Person('b');  
      var c = Person('c');  
      var d = Person('d');  
      var e = Person('e');  
      var chain1 = Chain([a]);  
      var chain2 = Chain([b]);  
      assert.equal(numberGenerationToCommonAncestor(chain1, chain2), 0);  
      var chain1 = Chain([c, b]);  
      var chain2 = Chain([b]);  
      assert.equal(numberGenerationToCommonAncestor(chain1, chain2), 2);  
      var chain1 = Chain([c, a]);  
      var chain2 = Chain([d, a]);  
      assert.equal(numberGenerationToCommonAncestor(chain1, chain2), 3);  
      var chain1 = Chain([c, a, b]);  
      var chain2 = Chain([d, a, b]);  
      assert.equal(numberGenerationToCommonAncestor(chain1, chain2), 0);  
 });  
 QUnit.test("Person.inbreedingCoefficient.notInbred", function( assert ) {  
      var a = Person('a');  
      var b = Person('b');  
      var x = Person('x', a, b);  
      assert.equal(x.inbreedingCoefficient(), 0);  
 });  
 QUnit.test("Person.inbreedingCoefficient.fullSibling", function( assert ) {  
      var a = Person('a');  
      var b = Person('b');  
      var c = Person('c', a, b);  
      var d = Person('d', a, b);  
      var x = Person('x', c, d);  
      assert.equal(x.inbreedingCoefficient(), 0.25);  
 });  
 QUnit.test("Person.inbreedingCoefficient.halfSibling", function( assert ) {  
      var a = Person('a');  
      var b = Person('b');  
      var c = Person('c');  
      var d = Person('d', a, b);  
      var e = Person('e', b, c);  
      var x = Person('x', d, e);  
      assert.equal(x.inbreedingCoefficient(), 0.125);  
 });  
 QUnit.test("Person.inbreedingCoefficient.fatherDaught", function( assert ) {  
      var a = Person('a');  
      var b = Person('b');  
      var c = Person('c', a, b);  
      var x = Person('x', a, c);  
      assert.equal(x.inbreedingCoefficient(), 0.25);  
 });  
 QUnit.test("Person.inbreedingCoefficient.firstCousin", function( assert ) {  
      var a = Person('a');  
      var b = Person('b');  
      var c = Person('c', a, b);  
      var d = Person('d', a, b);  
      var e = Person('e');  
      var f = Person('f');  
      var g = Person('g', c, e);  
      var h = Person('h', d, f);  
      var x = Person('x', g, h);  
      assert.equal(x.inbreedingCoefficient(), 0.0625);  
 });  
 QUnit.test("Person.inbreedingCoefficient.complex", function( assert ) {  
      var F = Person('F');  
      var E = Person('E');  
      var G = Person('G');  
      var M = Person('M');  
      var C = Person('C', F, E);  
      var D = Person('D', E, G);  
      var H = Person('H', G, M);  
      var A = Person('A', C, D);  
      var B = Person('B', A, H);  
      var X = Person('X', A, B);  
      assert.equal(X.inbreedingCoefficient(), 0.3125);  
 });  
 QUnit.test("Person.inbreedingCoefficient.deepInbred", function( assert ) {  
      var a = Person('a');  
      var b = Person('b');  
      var c = Person('c', a, b);  
      var d = Person('d', a, b);  
      var e = Person('e', c, d);  
      var f = Person('f', c, d);  
      var g = Person('g', e, f);  
      var h = Person('h', e, f);  
      var x = Person('x', g, h);  
      assert.equal(x.inbreedingCoefficient(), 0.5);  
 });  

html
 <!DOCTYPE html>  
 <html>  
 <head>  
  <meta charset="utf-8">  
  <title>QUnit basic example</title>  
  <link rel="stylesheet" href="https://code.jquery.com/qunit/qunit-2.0.1.css">  
 </head>  
 <body>  
  <div id="qunit"></div>  
  <div id="qunit-fixture"></div>  
  <script src="https://code.jquery.com/qunit/qunit-2.0.1.js"></script>  
  <script type="text/javascript" src="inbreeding.js"></script>  
  <script type="text/javascript" src="tests.js"></script>  
 </body>  
 </html>  

Wednesday 9 November 2016

Javascript module

Module is the common usage of closure.

 function User(){  
      var username, password;  
      function doLogin(user,pw) {  
           username = user;  
           password = pw;  
           // do the rest of the login work  
      }  
      var publicAPI = {  
           login: doLogin  
      };  
      return publicAPI;  
 }  

Usage

 var fred = User();  
 fred.login('fred', '123');  

Attempt to access the invisible method doLogin() will generate an error

 fred.doLogin('fred', '123');  

TypeError: fred.doLogin is not a function