Function

In JavaScript, functions are divided into declarative functions and anonymous functions.

Declarative function

Declarative functions are interpreted only once when the page is loaded. Once interpreted, the function is executed each time it is called. A declarative function creates the function keyword, function name, argument list, and function body with the following syntax:

function functionName (arg1, arg2,,,argN) {
	//Execution syntax
}
function add(a,b) {
	return a + b;
}
alert(add(3,4));

Anonymous function

An anonymous function is a function that is created dynamically at runtime.

var multiply = function(a, b) {
	return a * b
};
alert(multiply(3,4));

You can create an anonymous function using the Function's constructor. But it is not used often.

var minus = new Function('a','b', 'return a - b');
alert(minus(3,4));

Self-Executing Anonymous Functions

If you enclose the function with '(' and ')();', the function in parentheses is executed immediately.
Self-Executing Anonymous Functions are often found in JavaScript library code, such as jQuery.

(function() {
	alert("Hello World!");
})();
(function(whom) {
	alert("Hello " + whom);
})('John Doe');
(function(a, b) {
	alert(a + b);
})(2,5);

Scoping and Hoisting

Scoping is a rule that determines the effective area of a variable.
Understanding scoping requires an understanding of hoisting.
Hoisting refers to the action of a JavaScript interpreter to 'raise a declared variable or function to the top of the current execution area'.

The assignment statement is not subject to hoisting because it is done during runtime.
For reference, hoisting is not an official term in JavaScript.

In Java, variables declared in a block are valid only within a block.
In JavaScript, however, such variables can only be created within a function.
In JavaScript, you can not create variables that are valid only in the {} and if statement blocks.

Predict the results of the following code.

var x = 1;
function fn() {
	if (true) {
		var x = 10;
	}
	alert(x);
}
fn();
var x = 1;
function fn() {
	x = 10;
	return;
}
fn();
alert(x);
var x = 1;
function fn() {
	x = 10;
	return;
	function x() {}
}
fn();
alert(x);

The identifier x of the fn() function is valid only within the fn() function.
Exactly the above source is interpreted as follows.

var x = 1;
function fn() {
	function x() {}
	x = 10;
	return;
}
fn();
alert(x);
var x = 1;
function fn() {
	function x() {}
	x = 10;
	return x;
}
var retVal = fn();
alert(retVal);
alert(x);

In JavaScript, you can not create variables that are valid only in the {} and if statement blocks.

var x = 1;
alert(x);
if (true) {
	var x = 2;
	alert(x);
	x++;
}
alert(x);
function foo() {
	var x = 1;
	if (x) {
		(function () {
			var x = 2;
			alert(x);
		}());
	}
	alert(x);
}
foo();

The above example declares var x = 2; in the function.
This x variable is a new variable with a valid region only within the function, and has no relation to the variable x (var x = 1;) outside the function.

var x = 10;
function fn() {
	alert(x);
	var x = 20;
	alert(x);
}
fn();
alert(x);

The above code is hoisted and interpreted as follows.

var x = 10;
function fn() {
	var x;
	alert(x);
	x = 20;
	alert(x);
}
fn();
alert(x);

In the above code, comment out the var x declared in the function fn() to see how the result will change.

sayHo(); //SayHo() comes first in the code.
function sayHo() { 
	alert("Ho");
}

The above code is hoisted and interpreted as follows.

function sayHo() { 
	alert("Ho");
}
sayHo();

The following code, which looks similar, throws an error.

sayHo(); //TypeError: sayHo is not a function
var sayHo = function() {
	alert("Ho");
}

The following is a more difficult example.

function bumpInto() {
	function greet() {
		alert("How You Doin?");
	}
	return greet();
	function greet() {
		alert("What's Up?");
	}
}
bumpInto();

The above code is hoisted and interpreted as follows.

function bumpInto() {
	function greet() {
		alert("How You Doin?");
	}
	function greet() {
		alert("What's Up?");
	}
	return greet();
}
bumpInto();

If the parameter list is different, will it overload as Java?

function bumpInto() {
	function greet() {
		alert("How You Doin?");
	}
	function greet(whom) { //Greet function with parameters
		alert("What's Up?");
	}
	return greet();
}
bumpInto();

JavaScript functions are not overloaded like Java.
The greet (whom) function declared later is executed.

The assignment statement is said to be non-hoisting because it is done during runtime.
Consider the following example.

function bumpInto() {
	var greet = function () {
		alert("How You Doin?");
	}
	return greet();
	var greet = function (whom) {
		alert("What's Up?");
	}
}
bumpInto();

The above code is hoisted and interpreted as follows.

function bumpInto() {
	var greet;
	var greet;
	greet = function () {
		alert("How You Doin?");
	}
	return greet();
	greet = function (whom) {
		alert("What's Up?");
	}
}
bumpInto();

The greet() function that prints "What's Up?" after the return statement has no chance to execute.

Closures

Inner function

JavaScript supports inner functions.
An inner function can use a variable declared in an outer function (wrapping inner function).

function fn() {
	var balance = 0; //outside variable
	function deposit(money) { //inner function
		balance += money;
		alert(balance);
	}
	deposit(100);
}
fn();

There is no way to call an internal function directly outside the parent function, but there is a way to execute the internal function outside the parent function.
"A JavaScript function is basically a function object, so you can assign a function to a variable or pass it as an argument to another function."
The code returns a reference to the inner function so that it can be referenced outside the parent function.
By returning a reference to the inner function in the above example, you can change it to be able to reference it outside of the parent function.

function fn() {
	var balance = 0; //outside variable
	function deposit(money) { //inner function
		balance += money;
		alert(balance);
	}
	alert("The fn() function is executed.");
	return deposit;
}
var retFn = fn();//If the function fn does not return, retFn is undefined.
retFn(200);

The fact that this code runs without problems makes the Java programmer uncomfortable.
In Java, local variables defined in a method disappear when the method terminates.
Likewise, when the fn() function is terminated, the local variables defined within the function should be removed, but the variable balance is still valid even though the fn() function returns a return value.
balance is still valid because retFn has a closure.
A closure is a special object made up of two.
The first is the function and the second is the environment in which the function was created.
Here, the environment is a variable that can be used when a function is created.
"retFn has a closure containing the deposit function and the balance variable."

function fn() {
	var balance = 0;
	function deposit(money) {
		balance += money;
		alert(balance);
	}
	return deposit;
}

var ac1 = fn();
alert("---ac1---");
ac1(50);
ac1(450);

var ac2 = fn();
alert("---ac2---");
ac2(2000);
ac2(500);

A closure is created when a function's internal functions are referenced outside the function.
The fact that an inner function can be called through a reference beyond its scope means that the function can still be called in the future, so JavaScript must keep the function.
If a variable is a local variable of a parent function, the inner function inherits the scope of the parent and can reference the variable.
If you call deposit() twice with the same reference variable, you can see that the value of the balance variable is accumulated.
ac1 (50); ac1 450;
ac2 (200); ac2 (500);
Also, in calls to the deposit() function that use different reference variables (ac1 and ac2), the balance variables increase independently of each other.

Shared variable between closures

function account(accountNo) {
	var balance = 0;
	
	function getAccountNo() {
		return accountNo;
	}
	function deposit(money) {
		balance += money;
	}
	function withdraw(money) {
		balance -= money;
	}
	function getBalance() {
		return balance;
	}
	return {
		"getAccountNo": getAccountNo,
		"deposit": deposit,
		"withdraw": withdraw,
		"getBalance": getBalance
	};
}

var ac1 = account('111');
ac1.deposit(1000);
ac1.withdraw(500);
alert(ac1.getAccountNo() + ': ' + ac1.getBalance());

var ac2 = account('222');
ac2.deposit(3000);
ac2.withdraw(1000);
alert(ac2.getAccountNo() + ': ' + ac2.getBalance());

The four internal functions refer to the same local variables and share the same scope of variables.
If the deposit() function increments the balance by 1000, the value of the increased balance will be the new starting value when withdraw () is called again.
When account() is called again like var ac2 = account('222');, a new instance of the closure with the same closed environment is created.

Object-oriented coding in JavaScript

In JavaScript, the following is similar to a class in Java.

function Account(accountNo,balance) {
	this.accountNo = accountNo.toString();
	this.balance = balance;
}
Account.prototype.getAccountNo = function () {
	return this.accountNo;
};
Account.prototype.getBalance = function () {
	return this.balance;
};
Account.prototype.deposit = function (money) {
	this.balance += money;
};
Account.prototype.withdraw = function (money) {
	this.balance -= money;
};

var ac1 = new Account('111',500);
ac1.deposit(1000);
ac1.withdraw(500);
alert(ac1.getAccountNo() + ': ' + ac1.getBalance());

var ac2 = new Account('222',1000);
ac2.deposit(3000);
ac2.withdraw(1000);
alert(ac2.getAccountNo() + ': ' + ac2.getBalance());
References