Adsense-HeaderAd-Script


Advertisement #Header

18 Jan 2016

Understanding Javascript for Java Programmers Part3: this context inside a closure


Weirdness of Javascript Continues


?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
function Student() {
   
  var c = 1;  // local variable inside Student Constructor function
  setInterval(  function counter()
                {
                    c++;        // closure func has access to outer Student function
                    console.log(c); // logs 2 3 4 5 ... after each 1000ms
                }
                , 1000
             );
}
var s = new Student();
function Student() {
  
  var c = 1;  // local variable inside Student Constructor function

  setInterval(  function counter() 
                {
                    c++;        // closure func has access to outer Student function
                    console.log(c); // logs 2 3 4 5 ... after each 1000ms
                }
                , 1000
             );
}

var s = new Student();

In the above program the closure counter() has access to value of c variable in above Student() Constructor Function.

Weirdness is with this context
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
this.d = 100;
function Student() {
   
  this.c = 1;  // 'this' is an instance of Student itself
  this.d = 1;
  setInterval(  function counter()
                {
                    this.c++;   // closure func doesnt have access to this.c of outer function
                    console.log(this.c); // logs 'NaN' after each second
                     
                    this.d++;   // closure func have access to global this.d
                    console.log(this.d); // logs 101  102  103  104 ... after each second
                }
                , 1000
             );
}
var s = new Student();
this.d = 100;
function Student() {
  
  this.c = 1;  // 'this' is an instance of Student itself
  this.d = 1;

  setInterval(  function counter() 
                {
                    this.c++;   // closure func doesnt have access to this.c of outer function
                    console.log(this.c); // logs 'NaN' after each second
                    
                    this.d++;   // closure func have access to global this.d
                    console.log(this.d); // logs 101  102  103  104 ... after each second
                }
                , 1000
             );
}

var s = new Student();

Closure function counter() doesnt have access to outer function Student() this context but has access to global this context

Workaround

1. Assign the value of this context to a variable
2. Use the new Arrow Function


1. Assign the value of this context to a variable

 
01
02
03
04
05
06
07
08
09
10
11
12
13
14
function Student() { 
   
  this.c = 1;  // 'this' is an instance of Student itself
  var outer = this// outer is a local var in Student() that captures the instance of this context
 
  setInterval(  function counter()
                {
                    outer.c++;  // closure func now have access to this.c of outer function using
                                // by passing the value of this to outer variable
                    console.log(outer.c); // logs 2  3  4  5 ... after each second
                }
                , 1000
             );
}
 
 
function Student() {  
  
  this.c = 1;  // 'this' is an instance of Student itself 
  var outer = this;  // outer is a local var in Student() that captures the instance of this context

  setInterval(  function counter() 
                {
                    outer.c++;  // closure func now have access to this.c of outer function using 
                                // by passing the value of this to outer variable
                    console.log(outer.c); // logs 2  3  4  5 ... after each second
                }
                , 1000
             );
}

2. Use the new Arrow Function =>


 
01
02
03
04
05
06
07
08
09
10
11
12
function Student() {   
  this.c = 1;  // 'this' is an instance of Student itself
 
  setInterval(  () =>
                    {
                        this.c++;   // closure func now have access to this.c of outer function
                        console.log(this.c); // logs 2  3  4  5 ... after each second
                    }
                , 1000
             );
}
var s = new Student();
 
 
function Student() {    
  this.c = 1;  // 'this' is an instance of Student itself 

  setInterval(  () =>
                    {
                        this.c++;   // closure func now have access to this.c of outer function 
                        console.log(this.c); // logs 2  3  4  5 ... after each second
                    }
                , 1000
             );
}
var s = new Student();

22 Dec 2015

JavaScript for Java Programmers :Closure and Variable Scope


1st let us take a look at Javascript Variable Scope and Hoisting.

For Java developers this would be a strange world by looking at how Variable Scope works in JavaScript.

Eg: Java program to demo variable scope for local and global variables.
?

  
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
public class studentShow{
     
    private static class Student
    {
        private  static String name="Anwar";
         
        private static void studentName(){
            System.out.println("Inside 1. name= "+name);
            String name = "Ravi";
            System.out.println("Inside 2. name= "+name);
        }
    }  
     
    public static void main(String args[])
    {
        System.out.println("Outside 1. name= "+Student.name);
        Student.studentName();
        System.out.println("Outside 2. name= "+Student.name);
    }
}

  
public class studentShow{
    
    private static class Student
    {
        private  static String name="Anwar";
        
        private static void studentName(){
            System.out.println("Inside 1. name= "+name);
            String name = "Ravi";
            System.out.println("Inside 2. name= "+name);
        }
    }   
    
    public static void main(String args[]) 
    {
        System.out.println("Outside 1. name= "+Student.name);
        Student.studentName();
        System.out.println("Outside 2. name= "+Student.name);
    }
}
Output
?

  
1
2
3
4
Outside 1. name= Anwar
Inside 1. name= Anwar
Inside 2. name= Ravi
Outside 2. name= Anwar

  
Outside 1. name= Anwar
Inside 1. name= Anwar
Inside 2. name= Ravi
Outside 2. name= Anwar

Now see how a similar program outputs in Javascript

  
01
02
03
04
05
06
07
08
09
10
11
12
13
14
var name = "Anwar"  // global variable
     
function studentName()
{
    console.log ("Inside 1. name= "+ name); // undefined;  Due to Variable Hoisting
    var name = "Ravi"; // local variable; only accessible in this studentName function​
    console.log ("Inside 2. name= "+ name); // Ravi
}
console.log ("Outside 1. name= "+name); // Anwar: the global variable
     
studentName();     
console.log ("Outside 2. name= "+name); // Anwar: the global variable

  
var name = "Anwar"  // global variable
    
function studentName()
{
    console.log ("Inside 1. name= "+ name); // undefined;  Due to Variable Hoisting
    var name = "Ravi"; // local variable; only accessible in this studentName function​
    console.log ("Inside 2. name= "+ name); // Ravi
}

console.log ("Outside 1. name= "+name); // Anwar: the global variable
    
studentName();      

console.log ("Outside 2. name= "+name); // Anwar: the global variable
Output
?

  
1
2
3
4
Outside 1. name= Anwar
Inside 1. name= undefined
Inside 2. name= Ravi
Outside 2. name= Anwar

  
Outside 1. name= Anwar
Inside 1. name= undefined
Inside 2. name= Ravi
Outside 2. name= Anwar
Variable Hoisting

Why we got undefined instead of Anwar?
In Javascript, all variable declarations are hoisted (lifted and declared) to the top of the function, if defined in a function, or the top of the global context, if outside a function.

Note: Only variable declarations are hoisted to the top, not variable initialization or assignments

So the above JavaScript program is seen by the JavaScript Engine as
?

  
1
2
3
4
5
6
7
8
function studentName()
{
    var name; // only declaration is hoisted to top of the function
    console.log ("Inside 1. name= "+ name); // Since initialization is not hoisted ;
                                            // current value is undefined
    name = "Ravi";
    console.log ("Inside 2. name= "+ name);
}

  
function studentName()
{
    var name; // only declaration is hoisted to top of the function
    console.log ("Inside 1. name= "+ name); // Since initialization is not hoisted ; 
                                            // current value is undefined
    name = "Ravi";
    console.log ("Inside 2. name= "+ name); 
}

 Local Variables
In JavaScript, another weird thing about variable scope is its based  on Function- level instead of Block-level Scope (variables scoped to surrounding curly brackets);

A JavaScript program to demo the Function level Variable scope
?

  
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
var age = 15;
     
function studentName() {
    var name = "Ravi"
    console.log ("1. Outside Block level name= "+ name); //Ravi
     
    if(age<18) {
        var name = "Master. "; //local variable;
        //for Java developers, name variable scope should be limited to if block
        console.log("Inside if Block - name= "+name); // Master
    }
    else {
        var name = "Mr. "//local variable;
        //for Java developers, name variable scope should be limited to else block
        console.log("Inside else Block - name= "+name);
    }
    console.log ("2. Outside Block level name= "+ name);  // outside if-else block
        //for Java developers, Output should be Ravi   
        // But since in JS, the there is no block-level variable scope just Function level scope
        // Master is  the value of name
}

  
var age = 15;
    
function studentName() {
    var name = "Ravi";  
    console.log ("1. Outside Block level name= "+ name); //Ravi
    
    if(age<18) {
        var name = "Master. "; //local variable;
        //for Java developers, name variable scope should be limited to if block
        console.log("Inside if Block - name= "+name); // Master
    }
    else {
        var name = "Mr. ";  //local variable;
        //for Java developers, name variable scope should be limited to else block
        console.log("Inside else Block - name= "+name);
    }
    console.log ("2. Outside Block level name= "+ name);  // outside if-else block
        //for Java developers, Output should be Ravi    
        // But since in JS, the there is no block-level variable scope just Function level scope
        // Master is  the value of name
}
Output
?

  
1
2
3
1. Outside Block level name= Ravi
Inside if Block - name= Master.
2. Outside Block level name= Master.

  
1. Outside Block level name= Ravi
Inside if Block - name= Master.
2. Outside Block level name= Master.

Global Scope if not Declared 

Any variable in a function that is not declared will become a global variable.

?

  
01
02
03
04
05
06
07
08
09
10
11
12
var name = "Anwar"  // global variable
console.log ("1. Outside name= "+ name);   
function studentName() {
    name = "Ravi"// global variable
    // If you don't declare your local variables with the var keyword,
    // they are part of the global scope
    console.log ("  Inside name= "+ name); //Ravi
}
     
studentName(); 
console.log ("2. Outside name= "+ name);

  
var name = "Anwar"  // global variable
console.log ("1. Outside name= "+ name);    

function studentName() {
    name = "Ravi";  // global variable
    // If you don't declare your local variables with the var keyword, 
    // they are part of the global scope
    console.log ("  Inside name= "+ name); //Ravi 
}
    
studentName();  
console.log ("2. Outside name= "+ name);
Output
?

  
1
2
3
1. Outside name= Anwar
  Inside name= Ravi
2. Outside name= Ravi

  
1. Outside name= Anwar
  Inside name= Ravi
2. Outside name= Ravi

All non-declared variables in JavaScript will pollute the global scope so its best pratice to declare as local variables inside Functions.


What is a closure?
A closure is an inner function that has access to the outer (enclosing) function’s variables & parameters.

The closure has three scope chains:
  1. it has access to its own scope (variables & parameters defined in its Function), 
  2. it has access to the outer function’s variables & parameters, and 
  3. it has access to the global variables.

Note : Inner function cannot call the outer function’s arguments object

eg: JS Demo of Closure
?

  
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
function studentTopRanks(firstRank, secondRank)
{
  var msg ="The Rank list : ";
   
  function print()
  {
    // print() is closure inner function
     
    // It has access to local variables of enclosed outer function
    // It also has access to parameters - firstRank, SecondRank
    // of enclosed outer function
     
    return msg + "1st rank - " + firstRank
             + ", 2nd rank - " + secondRank;
  }
   
  return print(); 
}
     
studentTopRanks('Ravi','Anwar');

  
function studentTopRanks(firstRank, secondRank) 
{
  var msg ="The Rank list : ";
  
  function print()
  {
    // print() is closure inner function
    
    // It has access to local variables of enclosed outer function
    // It also has access to parameters - firstRank, SecondRank 
    // of enclosed outer function
    
    return msg + "1st rank - " + firstRank
             + ", 2nd rank - " + secondRank;
  }
  
  return print();  
}
    
studentTopRanks('Ravi','Anwar');


Weirdness of Closures in JavaScript

1. Closures have access to the outer function’s variable even after the outer function returns
?

  
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
function studentTopRanks(firstRank)
{
  var msg ="The Rank list : ";
   
  function print(secondRank)
  {
    // print() is closure inner function
     
    // It has access to local variables of enclosed outer function
    // It also has access to parameters - firstRank, SecondRank
    // of enclosed outer function
     
    return msg + "1st rank - " + firstRank
             + ", 2nd rank - " + secondRank;
  }
   
  return print; 
  // return print;   we return the print function object, instead of
  // return print(); which returns the String of the msg
   
}
     
var printObjVar = studentTopRanks('Ravi');
// At this juncture, the studentTopRanks outer function has returned.
// It returns a function Object and assigned to variable printObjVar
var display = printObjVar("Jackson");
// The closure (print) is called here after the outer function has returned above
// Yet, the closure still has access to the outer function's variables and parameter
console.log(display);

  
function studentTopRanks(firstRank) 
{
  var msg ="The Rank list : ";
  
  function print(secondRank)
  {
    // print() is closure inner function
    
    // It has access to local variables of enclosed outer function
    // It also has access to parameters - firstRank, SecondRank 
    // of enclosed outer function
    
    return msg + "1st rank - " + firstRank
             + ", 2nd rank - " + secondRank;
  }
  
  return print;  
  // return print;   we return the print function object, instead of
  // return print(); which returns the String of the msg
  
}
    
var printObjVar = studentTopRanks('Ravi'); 
// At this juncture, the studentTopRanks outer function has returned.
// It returns a function Object and assigned to variable printObjVar

var display = printObjVar("Jackson");
// The closure (print) is called here after the outer function has returned above
// Yet, the closure still has access to the outer function's variables and parameter
console.log(display);


2. Closures store references to the outer function’s variables; not the actual value.

Douglas Crockford demonstrated the use of Private Members in JavaScript using this technique.

?

  
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
function Student()
{
    var name = "Master";
    return {
         
    // We are returning an object with some inner functions
    // All the inner functions have access to the outer function's variables
     
        getName: function() 
        {
            // This inner function will return current value of
            // outer functions name variable
            // Even after the setName function changes it
          return name;
        },
        setName: function(newName) 
        {
            // This inner function will change the outer function's variable anytime
            name = newName;
        }
    }
}
var studObjVar = Student(); // At this juncture, the Student outer function Object has returned.
studObjVar.getName(); // Master
studObjVar.setName("Ravi"); // Changes the outer function's variable
studObjVar.getName(); // Ravi: It returns the updated celebrityId variable

  
function Student() 
{
    var name = "Master";
    return {
        
    // We are returning an object with some inner functions
    // All the inner functions have access to the outer function's variables
    
        getName: function()  
        {
            // This inner function will return current value of 
            // outer functions name variable
            // Even after the setName function changes it
          return name;
        },
        setName: function(newName)  
        {
            // This inner function will change the outer function's variable anytime
            name = newName;
        }
    }
}

var studObjVar = Student(); // At this juncture, the Student outer function Object has returned.
studObjVar.getName(); // Master
studObjVar.setName("Ravi"); // Changes the outer function's variable
studObjVar.getName(); // Ravi: It returns the updated celebrityId variable


19 Dec 2015

Understanding Javascript for Java Programmers


OOPS Javascript 

Yes, Javascript is Object Oriented  but has no class. Yikes!!!

Javascript is weird for Java Programmers

What do you mean Javascript has no Class?

In Java we have templates to define an Object 
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
    public static class Student
    {
        //properties
        private String name;
        private int[] marks = new int[3];
         
        //Constructor
        public Student(String name,int[] marks)
        {
            this.name =name;
            this.marks = marks;
        }
         
        //Method
        private int sum(){
            return marks[0]+marks[1]+marks[2];
        }
    }  
     
    public static void main(String args[])
    {
        int[] s1Marks = {75,84,90};
         
// Object instance s1 is created from Student class
// s1 is the object
        Student s1 = new Student("Ravi" ,s1Marks); 
         
        int s1Total = s1.sum();
    }

    public static class Student
    {
        //properties
        private String name;
        private int[] marks = new int[3];
        
        //Constructor
        public Student(String name,int[] marks)
        {
            this.name =name;
            this.marks = marks;
        }
        
        //Method
        private int sum(){
            return marks[0]+marks[1]+marks[2];
        }
    }   
    
    public static void main(String args[]) 
    {
        int[] s1Marks = {75,84,90};
        
// Object instance s1 is created from Student class
// s1 is the object
        Student s1 = new Student("Ravi" ,s1Marks);  
        
        int s1Total = s1.sum();
    }

In above Java program, Student class is the template for the object.
s1, s2 are the real objects.

But for Javascript, theres is no class, after creating a object, its properties and methods can be dynamically added.

?
01
02
03
04
05
06
07
08
09
10
11
12
13
//Object created
var Student = new Object();
//Object properties added later
Student.name = "Ravi";
Student.marks = [75,84,90];
//Object methods added later
Student.sum = function(){
                return this.marks[0]+this.marks[1]+this.marks[2];
            }
s1Total.innerHTML = Student.sum();

  
//Object created
var Student = new Object();

//Object properties added later
Student.name = "Ravi";
Student.marks = [75,84,90];

//Object methods added later
Student.sum = function(){
                return this.marks[0]+this.marks[1]+this.marks[2];
            }

s1Total.innerHTML = Student.sum();


Other ways to create Javascript Objects

?
01
02
03
04
05
06
07
08
09
10
11
12
13
//Object created
var Student = {
    //properties
    name  : "Ravi",
    marks : [75,84,90],
     
    //methods
    sum   : function(){
                    return this.marks[0]+this.marks[1]+this.marks[2];
            }
}
s1Total.innerHTML = Student.sum();

  
//Object created
var Student = {

    //properties
    name  : "Ravi",
    marks : [75,84,90],
    
    //methods
    sum   : function(){
                    return this.marks[0]+this.marks[1]+this.marks[2];
            }
}
s1Total.innerHTML = Student.sum();

Function is an Object too. What did u just say 'function?
Yes, Javascript is so much object oriented that even the methods or functions are Objects too.
In Javascript, Function can be
        • assigned to Variables
        • stored inside Arrays
        • passed as Parameters
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
//Function Object 
var sum   = function(marks){
                    return marks[0]+marks[1]+marks[2];
            }
             
var s1 = {
    //properties
    name    : "Ravi",
    marks   : [75,84,90],
     
    //function object as argument
    print   : function(msg,func)
            {
                return this.name + msg + func(this.marks);
            }
}
//sum function is passed as parameter
s1Total.innerHTML = s1.print("'s Total marks =",sum);

  
//Function Object created
var sum   = function(marks){
                    return marks[0]+marks[1]+marks[2];
            }
            
var s1 = {
    //properties
    name    : "Ravi",
    marks   : [75,84,90],
    
    //function object as argument
    print   : function(msg,func)
            {
                return this.name + msg + func(this.marks);
            }
}
//sum function is passed as parameter
s1Total.innerHTML = s1.print("'s Total marks =",sum);

In above example, function Object is 1st created and assigned to a variable sum
The sum function Object is passed as parameter to the s1 Object's print method

We can get some feel of Class like templating of Java by using Constructor Function & new operator. Constructor function is just like a normal function where its properties are initialised by the passed parameters.
new operator is used to create a new Object.

?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
//Constructor Function  created
function Student(name,marks)
{
    this.name   = name;
    this.marks  = marks;
    this.sum    = function(){
                    return this.marks[0]+this.marks[1]+this.marks[2];
                }
}
// new Object created & initialized        
var s1 = new Student("Ravi", [75,84,90]);
var s2 = new Student("Anwar",[70,83,97]);
s1Total.innerHTML = s1.sum();

  
//Constructor Function  
function Student(name,marks)
{
    this.name   = name;
    this.marks  = marks;
    this.sum    = function(){
                    return this.marks[0]+this.marks[1]+this.marks[2];
                } 
}
// new Object created & initialized         
var s1 = new Student("Ravi", [75,84,90]);
var s2 = new Student("Anwar",[70,83,97]);

s1Total.innerHTML = s1.sum();

Now with Student constructor function we can initiliase every Object we want to use as a Student Object.

Now the simialr code if we try by adding sum method outside of the Student Constructor Function, the code fails.

?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
//Constructor Function
function Student(name,marks)
{
    this.name   = name;
    this.marks  = marks;
}
//Appending sum method to Student Object from outside of the Constructor function
Student.sum = function(){
                return this.name+ " got " +this.marks[0]+this.marks[1]+this.marks[2];
            }
// new Object created & initialized        
var s1 = new Student("Ravi", [75,84,90]);
s1Total.innerHTML = s1.sum(); // TypeError: s1.sum is not a function

  
//Constructor Function 
function Student(name,marks)
{
    this.name   = name;
    this.marks  = marks;
}
//Appending sum method to Student Object from outside of the Constructor function
Student.sum = function(){
                return this.name+ " got " +this.marks[0]+this.marks[1]+this.marks[2];
            } 
// new Object created & initialized         
var s1 = new Student("Ravi", [75,84,90]);

s1Total.innerHTML = s1.sum(); // TypeError: s1.sum is not a function

This where the similar code can be achieved by a prototype property that is present in all Javascript Objects.

Prototype Object
In Javascript, every object has a prototype property that reference its prototype Object. Any properties & methods that are part of an Object's prototype will appear as properties & methods of that Object itself.
?
1
2
3
4
5
//Appending sum method to prototype property of the Student Object
// Now sum becomes the method of Student Object
Student.prototype.sum = function(){
                return this.name+ " got " + (this.marks[0]+this.marks[1]+this.marks[2] );
            }

  
//Appending sum method to prototype property of the Student Object
// Now sum becomes the method of Student Object
Student.prototype.sum = function(){
                return this.name+ " got " + (this.marks[0]+this.marks[1]+this.marks[2] );
            } 

Now using prototype property the sum appears as the method of Student Object.


Private members
This is done by using Douglas Crockford technique. The local variables and parameters can both become private member by using Closure. Closure is just inner function has access to variables and parameters of outer function.

For more understanding of Closure and its private members technique, lets take that to next post.