JS Variable, Let, Functions, Scoping, and Closures. - Yash-777/SeleniumDriverAutomation GitHub Wiki

Javascript variables and Function

Hoisting is the JavaScript interpreter’s action of moving all variable and function declarations to the top of the current scope.

However, only the actual declarations are hoisted. by leaving assignments where they are.

  • variable's/Function's declared inside the page are global can access anywhere in that page.
  • variable's/Functions declared inside the function are having local scope. means they are available/accessed inside the function body (scope), they are not available outside the function body.

Variable

Javascript is called loosely typed language. Which means Javascript variables can hold value of any Data-Type. Javascript automatically takes care of changing the variable-type based on the value/literal provided during runtime.

NOTE: A variable declared using the var or let statement with no assigned value specified has the value of undefined.

global_Page = 10;                                                       var global_Page;      « undefined
	« Integer literal, Number Type.       -------------------      	global_Page = 10;     « Number         
global_Page = 'Yash';                         |   Interpreted   |      	global_Page = 'Yash'; « String
	« String literal, String Type.        «       AS        «      	global_Page = true;   « Boolean 
var global_Page = true;                       |                 |      	global_Page = function (){      « function
	« Boolean Type                        -------------------             var local_functionblock;  « undefined
global_Page = function (){                                                local_functionblock = 777;k;  « Number
	var local_functionblock = 777;                                  };  
	// Assigning function as a data.
};	

Declaring variables

You can declare a variable in three ways:

  • With the keyword var. For example, var x = 42. This syntax can be used to declare both local and global variables.
  • By simply assigning it a value. For example, x = 42. This always declares a global variable, if it is declared outside of any function. It generates a strict JavaScript warning. You shouldn't use this variant.
  • With the keyword let. For example, let y = 13. This syntax can be used to declare a block-scope local variable. See Variable scope below.

let

The let statement declares a block scope local variable, optionally initializing it to a value.

Description let allows you to declare variables that are limited in scope to the block, statement, or expression on which it is used. This is unlike the var keyword, which defines a variable globally, or locally to an entire function regardless of block scope.

let doesn't allows multiple declaration with same name inside its scope.

var if multiple declaration are available then it overrides its parent scope.

(function varTest() {
  var x = 1;
  if (true) {
    var x = 2;  // same variable! Overrides with parent variable.
    x = 7;
    console.log('Var Override : ',x);  // 1 - 2 - 7
  }
  x = 77;
  console.log('Var block scope : ', x);  // 1 - 2 - 7 - 77
})();

(function letTest() {
  let x = 1;
  if (true) {
    let x = 2;  // different variable
    x = 77;
    //let x = 7; //Identifier 'x' has already been declared.
    console.log('Let block scope, which will not allow another declaration with same name in current block : ', x);  // 2 - 77
  }
  x = 777;
  console.log('Let block scope, which will not allow another declaration with same name in current block : ', x);  // 1 - 777
})();

Const

Constants are block-scoped, much like variables defined using the let statement. The value of a constant cannot change through re-assignment, and it can't be redeclared.

// define MY_FAV as a constant and give it the value 7
const MY_FAV = 7;

// this will throw an error
MY_FAV = 20;

eval()

The eval() function evaluates JavaScript code represented as a string.

eval(new String('2 + 2')); // returns a String object containing "2 + 2"
eval('2 + 2');             // returns 4

Function

Functions are one of the fundamental building blocks in JavaScript. A function is a JavaScript procedure—a set of statements that performs a task or calculates a value. To use a function, you must define it somewhere in the scope from which you wish to call it.

function Identifier_opt ( FormalParameterList_opt ) { 
	FunctionBody | sequence of statements

	« return;  Default undefined
	« return 'some data';
}
  • functions declared inside the page are hoisted to top of the page having global access.

  • functions declared inside the function-block are hoisted to top of the block.

  • Default return value of function is 'undefined', Variable declaration default value also 'undefined'

     Scope with respect to function-block global. 
     Scope with respect to page undefined | not available.
    

Function Declaration

function globalAccess() {                                  function globalAccess() {      
}                                  -------------------     }
globalAccess();                    |                 |     function globalAccess() { « Re-Defined / overridden.
localAccess();                     «   Hoisted  As   «         function localAccess() {
function globalAccess() {          |                 |         }
	 localAccess();            -------------------         localAccess(); « function accessed with in globalAccess() only.
	 function localAccess() {                          }
	 }                                                 globalAccess();
}                                                          localAccess(); « ReferenceError as the function is not defined

Function Expression

            10;   				« literal
	   (10);  				« Expression  		(10).toString() -> '10'
var a;                      
	a = 10;   				« Expression var          a.toString()  -> '10'
(function invoke() {                            « Expression Function
 console.log('Self Invoking');        				    (function () {
});									         }) () -> 'Self Invoking'

var f; 
    f = function () {                           « Expression var Function
	console.log('var Function');                                f ()  -> 'var Function'
    };

Function assigned to variable Example:

(function selfExecuting(){
	console.log('IIFE - Immediately-Invoked Function Expression');
}());

var anonymous = function (){
	console.log('anonymous function Expression');
};

var namedExpression = function for_InternalUSE(fact){
	if(fact === 1){
		return 1;
	}

	var localExpression = function(){
		console.log('Local to the parent Function Scope');
	};
	globalExpression = function(){ 
		console.log('creates a new global variable, then assigned this function.');
	};
	
	//return; //undefined.
	return fact * for_InternalUSE( fact - 1);	
};

namedExpression();
globalExpression();


javascript interpreted as

var anonymous;
var namedExpression;
var globalExpression;

anonymous = function (){
	console.log('anonymous function Expression');
};

namedExpression = function for_InternalUSE(fact){
	var localExpression;
	
	if(fact === 1){
		return 1;
	}
	localExpression = function(){
		console.log('Local to the parent Function Scope');
	};
	globalExpression = function(){ 
		console.log('creates a new global variable, then assigned this function.');
	};
	
	return fact * for_InternalUSE( fact - 1);	 // DEFAULT UNDEFINED.
};

namedExpression(10);
globalExpression();

jsperf

Note : In browser engine this, which always refers to the global object - 'window'

(function(windowTab){
console.log('\n Application URL « ', windowTab.location.href); 
})(this);
==================================================================================
(function(element){
console.log('\n selfinvoking function with documnet Element as a parameter');
    element.style.color = "green";

})(document.getElementById("search")); // wiki-rightbar
==================================================================================
function myNamedFunction() {
    console.log('\n Calling in selfinvoking function');
    var myArray = ["Yash-777"];
    return myArray;
}
(function( functionReturnedValue ) {
    console.log('Function returned value : ', functionReturnedValue);
})( myNamedFunction () );
==================================================================================
(function ( f ) {
    console.log('\n selfinvoking function with function as a parameter \n« String : ', f().stringKey, '\n Function : ', f().fnctionKsy () );
})(
function functionAsParameter() {
    console.log('function as a Parameter');
	// Functional scoped value
    var stringVal = "Yash-777";
    return {
		stringKey : stringVal,
		fnctionKsy : function () {
			return 'json key function expression';
		}
	};
}
);

Output of the above script comes like this.

 Application URL «  http://stackoverflow.com/questions/406192/get-current-url-in-javascript/38199254#38199254
==================================================================================
 selfinvoking function with documnet Element as a parameter
 ==================================================================================
 Calling in selfinvoking function
 Function returned value :  ["Yash-777"]
================================================================================== 
 function as a Parameter
 function as a Parameter
 
 selfinvoking function with function as a parameter 
« String :  Yash-777 
 Function :  json key function expression

The Global Object

When a function is called without an owner object, the value of this becomes the global object.

In a web browser the global object is the browser window.

Note that this is not a variable. It is a keyword. You cannot change the value of this.

function thiskeyword() {
	var a = 10;
	function b() {
		for(var i = 0; i < arguments.length; i++) {
			console.log('arguments[',i,'] : ', arguments[i]);
		}
		this.a = 20;
		console.log('Global Val: ', window.a);
		console.log('Local Scope Val : ', a);
	}
	b(10, 20);
	console.log('Global Val: ', window.a);
	console.log('Local Scope Val : ', a);
	
	a = this.a = 40;
	console.log('Global Val: ', window.a);
	console.log('Local Scope Val : ', a);
}
thiskeyword();

Invoking a Function with a Function Method

In JavaScript, functions are objects. JavaScript functions have properties and methods.

call() and apply() are predefined JavaScript function methods. Both methods can be used to invoke a function, and both methods must have the owner object as first parameter.

function myFunction(a, b) {
    return a * b;
}
var myObjectPar = myFunction.call(myObjectPar, 10, 2);     // Will return 20

myArray = [10, 2];
var myObjectArr = myFunction.apply(myObjectArr, myArray);  // Will also return 20

Both methods take an owner object as the first argument. The only difference is that call() takes the function arguments separately, and apply() takes the function arguments in an array.


Lexical scoping:

Variables declared outside of a function are global variables and are visible everywhere in a JavaScript program. Variables declared inside a function have function scope and are visible only to code that appears inside that function

var scope = "I am global"; // Global Scope Variable Declaration
var globalDec = "Global Scope - Variable Declaration";
function whatismyscope() {
   var scope = "I am just a local"; // Function Scope Variable Declaration, Declarion Hoist to top of its scope.
   console.log('Lexcal Scope : ', scope);
   globalDec = "Global Scope - Variable Assignment";
}
whatismyscope();
console.log('Global Scope : ', scope);
console.log('Variable Declaration & Assignment : ', globalDec );

Output:
Lexcal Scope :  I am just a local
Global Scope :  I am global
Variable Declaration & Assignment :  Global Scope - Variable Assignment

First it checks for the variable value inside the current scope, if not available searches in parent scope and so on.. If the variable value is not available on any of the scope then the value is 'undefined'.


Closures

A closure is the combination of a function and the lexical environment within which that function was declared.

var nonClouser = (function() {
    var a = 7;
    return {
       a
    };
})();
console.log('Only lexical environment, with out any inner function : ', nonClouser); // Object {a: 7}

Whenever you use function inside another function, a closure is used.

A closure in JavaScript is like maintaining a copy of all the local variables of its parent function by the innerFunctions.

var clouserParanthesis = (function() {
    var a;
    return {
       setA(param) { a = param; },
       getA : function() { return a; }
    };
})();
clouserParanthesis.setA(777);
console.log('lexical|functional environment Vlaue : ', clouserParanthesis.getA());
console.log('lexical|functional environment and inner function access to outer function scope variables : ', clouserParanthesis );

closure wiki (also lexical closures or function closures): closure's copies are function with preserved data.

Each closure's copies are created to a function with their own free values or references(variables that are used locally, but defined in an enclosing scope). A closure—unlike a plain function—allows the function to access those captured variables through the closure's copies of their values or references, even when the function is invoked outside their scope.

function startAt(x) {
   function incrementBy(y){
	return x + y;
   }

   return incrementBy;
}
var closureCopie1 = startAt(1)
var closureCopie2 = startAt(5)


console.dir( closureCopie1 )
console.dir( closureCopie2 )

console.log('Defining values in Enclosing function scope : ', closureCopie1(5));
console.log('Defining values in Enclosing function scope : ', closureCopie2(7));

Practical closures Closures are useful because they let you associate some data (the lexical environment) with a function that operates on that data. This has obvious parallels to object oriented programming, where objects allow us to associate some data (the object's properties) with one or more methods.

Example JSFiddle:

function makeSizer(size) {
  return function() {
    document.body.style.fontSize = size + 'px';
  };
}

var size12 = makeSizer(12);
var size14 = makeSizer(14);
var size16 = makeSizer(16);

document.getElementById('size-12').onclick = size12;
document.getElementById('size-14').onclick = size14;
document.getElementById('size-16').onclick = size16;

Difference between Function constructor and function declaration

Functions created with the Function constructor do not create closures to their creation contexts; they always are created in the global scope. When running them, they will only be able to access their own local variables and global ones, not the ones from the scope in which the Function constructor was called. This is different from using eval with code for a function expression.

var declaration = function f() {
  console.dir('Function Declaration');
}
declaration ();
var constructor = new function() {
  console.dir('Function Constructor');
}
declaration ();
// constructor(); //  constructor is not a function(…)
/*Output:
VM223:2 Function Declaration
VM223:7 Function Constructor
VM223:2 Function Declaration */