Monday, July 30, 2018

Javascript ES6 - lexical scope of this

In Javascript every function brings its own 'this' context. The situation becomes difficult to work with when there are many functions inside function which complicates the context of 'this'. The ES6 fat arrow (=>) passes the lexical scope of parent 'this' to all child functions -

Example:
function parentFunction(){
    this.add = 0;
    this.addAnother = function(){
    this.addOne = setTimeout(function(){
        console.log(++this.add);
        }, 1000)
    }
} 

var funcObj = new parentFunction();
funcObj.addAnother(); // NaN  

It outputs to 'NaN' because the 'this' context here 'console.log(++this.add);' is scoped to setTimeout function.

To avoid this, the ES5 solution is to use the classic 'var that = this' -
function parentFunction(){
    this.add = 0;
    var that = this;
    this.addAnother = function(){
    this.addOne = setTimeout(function(){
        console.log(++that.add);
        }, 1000)
    }
} 

var funcObj = new parentFunction();
funcObj.addAnother();  

Now, this works perfectly fine, but the new ES6 fat arrow works even better by passing the lexical scope of parent 'this' to all child functions -
function parentFunction(){
    this.add = 0;
    this.addAnother = () => {
    this.addOne = setTimeout(() => {
        console.log(++this.add);
        }, 1000)
    }
} 

var funcObj = new parentFunction();
funcObj.addAnother();  

The traditional ES5 'this' creates a new scope of 'this' in each function which is why we were getting the 'NaN' because the 'this' in setTimeout function was scoped to the setTimeout function alone.

With the fat arrow, the 'this' in setTimeout refers to the lexical scope of parent 'this'.




Friday, July 27, 2018

Javascript: Var vs Let vs Const

The var, let and const game is all about their scope (the location where they are available to the developers). Put it simply -
  • Var has a functional scope (local and global/window), also it goes all the way up till the window object to find the declaration. Var is also a function scope (they are available inside the function they are declared in)   
  • Let has a block level scope. It stays within the curly braces. Let allows re-assigning its values  
  • Const also has a block level scope. Use const if you do not need to change its value 

Let's go with examples:

Var:
for(var i = 0; i < 10; i++){
    console.log(i);
}
It's normal to consider that the scope of 'var i' would be available inside the curly braces of for loop. However, the 'var i' is also accessible outside of the for loop.
for(var i = 0; i < 10; i++){
    console.log(i);
}
console.log('After loop is over ' +i); //logs 10 

It's completely valid because of the concept of 'Hoisting'. All variables in JavaScript are hoisted on top of the function - something like this:
var i; 
for(i = 0; i < 10; i++){
    console.log(i);
}
console.log('After loop is over ' +i);   

This is because there is only one type of scope in ES5 - that is Function Scope
function func(){ 
    for(var i = 0; i < 10; i++){
        console.log(i);
    }
}
func();
console.log('After the function ' +i); // throws an error, because var i is not accessible     

And if you don't declare the var keyword inside the function, the JS will hoist the var at the window/global level and it will be accessible everywhere  -
var i; // hoists in global scope 
function func(){ 
    for(i = 0; i < 10; i++){ // if you don't mention 'var i'
        console.log(i);
    }
}
func();
console.log('After the function ' +i); // logs 10      

Let:
Let will never have the issues like var, because let has a block level scope which means it doesn't work outside of that block of code, or outside of those curly braces -
 
for(let i = 0; i < 10; i++){
    console.log(i);
}
console.log('After loop is over ' +i); // doesn't work     

But you can re-assign the values of let -
 
let i = 'hi';
i = 55; 
console.log(i); // logs 55 

Const:
Changing const value is not possible -
 
const i = 10;
i = 55; 
console.log(i); // throws typeError  

But, it allows a little flexibility to change the property of const object  -
 
const i = {
    k: 10
}
i.k = 55; 
console.log(i); // logs k:55   




Sunday, May 20, 2018

Get form fields value using jQuery

In jQuery the .val() method is used to get form field values from input, textarea, select etc. Use the :checked method for select, checkbox, and radio buttons.

Here’s a Fiddle:

Friday, December 4, 2015

JavaScript Constructor Prototype

At first it's important to understand that in JavaScript every function is an Object. Ok - then, what is a Constructor function?

The Construction function in javascript is just like any other function. Except, the convention it follows - Capitalization. The first character is in capital format. Another difference is that it uses the 'this' keword of javascript, which is the most important and confusing keyword of all.

This is how we create the constructor function:
function Student(name){
  this.name = name;
  this.getName = function(){
    return this.name;    
  }
}
var s1 = new Student("Leo");
var s2 = new Student("Lara");

console.log(s1.getName()); //Leo
console.log(s2.getName()); //Lara
This is not an appropriate way because if you create 500 Student objects then there will be 500 copies of the getName() function in memory.

Approach 2:
function Student(name){
  this.name = name;
}
var s1 = new Student("Leo");
s1.getName = function(){
  return this.name;
}
var s2 = new Student("Lara");

console.log(s1.getName()); //Leo
console.log(s2.getName()); //TypeError: s2.getName is not a function
The problem with this approach is that you have to repeat the same function for each object you create which will be arror prone.

Approach 3:
function Student(name){
  this.name = name;
}
Student.getName = function(){
  return this.name;
}
var s1 = new Student("Leo");
var s2 = new Student("Lara");

console.log(s1.getName()); //TypeError: s1.getName is not a function
console.log(s2.getName()); // 
The problem with this approach is that our newly created objects don't have access to the getName function.

Let's use the prototype property to associate the function
function Student(name){
  this.name = name;
}
Student.prototype.getName = function(){
  return this.name;
}
var s1 = new Student("Leo");
var s2 = new Student("Lara");

console.log(s1.getName()); //Leo
console.log(s2.getName()); //Lara

1. The benefits of this approach is that no matter how many objects you create, functions are loaded only once in the memory.
2. It allows you to override the function if necessary



Thursday, December 3, 2015

JavaScript: Prototype Object Vs Reference Object Explained

What is an Object?
It is a set of key and value pairs. You can use any number of keys with any name as long as it is a String. And each key can be associated with any value, those values can be of any Types, such as: Primitive Types, Function Objects and object itself.
var myObject = {
  a: undefined, //Primitive
  b: null, //Primitive
  c: true, //Primitive
  d: "foo", //Primitive
  e: 4.33, //Primitive
  f: function bar() { /**/ }, //Object
  g: {
    h: baz
  } //Object
}

The difference:

In case of Objects - values are passed by reference, and the changes are bi-directional:
var a = { x: 1, y: 2}
var b = a;
console.log(b); // Object {x: 1, y: 2} 

//
b.x = 10;
console.log(a.x); // 10

//
a.y = 20;
console.log(b.y); //20

While in Primitive - the values are passed by value, and the changes are uni-directional:
//Prototype Object
var object1 = {x: 11, y: 22};
var object2 = Object.create(object1);
console.log(object2); //Object {}

//
object2.x = 100; 
console.log(object1.x); //11 
console.log(object2.x); //100 

//
object1.y = 200; 
console.log(object2.y); //200 
console.log(object1.y); //200 

Fiddle: http://jsfiddle.net/sL6q0742/



Sunday, December 28, 2014

Vertical text / tabs with CSS3 transform matrix

These days the UI trends are changing rapidly, everyone is trying to implement something different than regular. For a long time we have always implemented the tabs in horizontal format, we did try to keep the tabs in vertical format but it wasn't easily possible with creepy IE browsers. CSS3 transforms have made the web a lot different than before. Scaling, skewing, rotating, translates are doing beautiful magic with their capabilities.

Today, implementing vertical text / tabs is possible with CSS3 transform matrix. Here is the code -

Browser compatibility: IE 9+

HTML:
  • Tab 3
  • Tab 2
  • Tab 1

CSS:
.tabs-vertcal{ 
 transform-origin: 0% 0% 0px; 
 transform: matrix(0, -1, 1, 0, 0, 350); 
}
.tabs{
 list-style-type: none;
}
.tab{
 float: left; 
 width: 92px; 
 padding: 6px; 
 border: 1px solid pink; 
 background: indigo; 
 color: white;
 text-align: right;
}

Demo: http://jsfiddle.net/oy3gnuxr/1/



Note: It's just a vertical text for now, I'll add the tabs functionality with jQuery soon.


Thursday, November 20, 2014

CSS Tabs Navigation Tricks

Developing a tabs navigation with CSS holds some simple tricks, but most of the front-end guys end up getting the results in an inappropriate way. Here's what you need to know about it -
I. The margin-bottom: -1px to the <li> element
II. The border and background to the <a> element
III. Change in border and background in the <a> element when <li> has .active class

HTML: 

CSS: 
ul{ margin: 0; padding: 0; list-style: none; border-bottom: 1px solid #ddd; 
}
ul:before, ul:after{
    content: ""; display: table;
}
ul:after{
    clear: both;
}
/**/
ul li{ 
    float: left; 
    margin: 0 4px -1px 4px;                /*Trick 1*/
}
ul li a{ 
    display: block; 
    text-decoration: none; 
    padding: 10px 15px; 
    border: 1px solid transparent;         /*Trick 2*/
    background: transparent;               /*Trick 2*/ 
}
ul li a:hover{
    background: #eee;
}
ul li.active a{ 
    border-radius: 4px 4px 0 0;
    border: 1px solid #ddd; 
    border-bottom: 1px solid transparent; /*Trick 3*/ 
    background: #fff;                     /*Trick 3*/ 
}

jQuery: 
$(function(){
    $('li a').on('click', function(e){
        e.preventDefault(); // to avoid page refresh because a elements have # in href 
        $('li').removeClass('active');
        $(this).parent('li').addClass('active');
    });
});


Demo: http://jsfiddle.net/dipaks2011/o35c8yxt/

Note: The fiddle demo is creating a ghost border on the right side of the tabs which doesn't appear in real HTML page.